WPF/MVVM 选项卡式设计 & 避免绑定错误
WPF/MVVM Tabbed Design & Avoiding Binding Errors
这是一个关于如何构建 MVVM/WPF 应用程序的 "best-practice design" 问题。
设想像 Photoshop 这样的东西,你有一个可以打开多个(选项卡式)文档和工具箱的编辑器。每个工具仅设置当前活动文档的 属性(例如打开过滤器和设置过滤器参数)。我正在为选项卡式界面使用 Actipro 的停靠和 MDI 框架。
支持两种类型的文档:称为 DocSimple 和 DocComplex,其中 DocComplex 提供 DocSimple 的所有可控属性,外加一些额外的属性。
我现在做了什么:
- MainWindow.xaml 和整个应用程序的 MainWindowViewModel(包含对接容器和 toolbox/tool 控件)
- MainWindowViewModel 有一个 ActiveDocViewModel 属性,它指向当前活动文档选项卡的 DocSimpleViewModel 或 DocComplexViewModel 实例(或 "null" 当没有文档选项卡打开时)。
- MainWindow 工具箱中的各种控件绑定到 ActiveDocViewModel 的各种属性(即 {Binding Path=ActiveDocViewModel.SomeProperty})。
问题 1:一般来说,这看起来是一种合理的方法吗?这是我的第一个 MVVM 应用程序(来自 WinForms),虽然一切正常,但我对绑定到 ActiveDocViewModel.Prop 是否可取有一些疑问......但它似乎也是最合乎逻辑的方法,基于事实上 "one" MainWindow 需要绑定到 "one of many possible" 文档选项卡。
问题 2:如前所述,DocComplex 比 DocSimple 提供更多 properties/options。我通过从 DocSimpleViewModel 继承 DocComplexViewModel 并在 MainWindowViewModel 中创建一个 属性 来处理这个问题,例如:
public bool IsComplexToolsVisible
{
get
{
return(ActiveDocViewModel != null && ActiveDocViewModel is DocComplexViewModel);
}
}
这绑定到工具箱该部分的 "Visibility"。同样,它按预期工作 - 但每当我们打开 DocSimple 时,它也会为复杂工具部分中的每个 属性 产生 "BindingExpression path error: 'xxx' property not found" 错误。通过向 DocSimple 添加 'stub' 属性来修复这些问题很容易,但这显然是错误的(使用继承将 "complex" 功能添加到 "simple" 基础有什么意义当我最终为基础 class 中的所有内容添加存根时键入?)。因此,这些绑定错误的存在让我质疑这种方法是否有缺陷 - 以及我如何在避免所有绑定错误的同时处理复杂与简单的场景。
任何见解将不胜感激:)
乍一看,总体结构在我看来非常好,但我不是专家,不想这样评价。
那么针对您的绑定错误问题:
您可以使用 TemplateSelector,它为 DocSimple 类型提供一个带有 "simple toolbox" 的模板和一个不同的模板,其中包含简单工具箱以及 DocComplex 的附加部分。
这是一个关于如何构建 MVVM/WPF 应用程序的 "best-practice design" 问题。
设想像 Photoshop 这样的东西,你有一个可以打开多个(选项卡式)文档和工具箱的编辑器。每个工具仅设置当前活动文档的 属性(例如打开过滤器和设置过滤器参数)。我正在为选项卡式界面使用 Actipro 的停靠和 MDI 框架。
支持两种类型的文档:称为 DocSimple 和 DocComplex,其中 DocComplex 提供 DocSimple 的所有可控属性,外加一些额外的属性。
我现在做了什么:
- MainWindow.xaml 和整个应用程序的 MainWindowViewModel(包含对接容器和 toolbox/tool 控件)
- MainWindowViewModel 有一个 ActiveDocViewModel 属性,它指向当前活动文档选项卡的 DocSimpleViewModel 或 DocComplexViewModel 实例(或 "null" 当没有文档选项卡打开时)。
- MainWindow 工具箱中的各种控件绑定到 ActiveDocViewModel 的各种属性(即 {Binding Path=ActiveDocViewModel.SomeProperty})。
问题 1:一般来说,这看起来是一种合理的方法吗?这是我的第一个 MVVM 应用程序(来自 WinForms),虽然一切正常,但我对绑定到 ActiveDocViewModel.Prop 是否可取有一些疑问......但它似乎也是最合乎逻辑的方法,基于事实上 "one" MainWindow 需要绑定到 "one of many possible" 文档选项卡。
问题 2:如前所述,DocComplex 比 DocSimple 提供更多 properties/options。我通过从 DocSimpleViewModel 继承 DocComplexViewModel 并在 MainWindowViewModel 中创建一个 属性 来处理这个问题,例如:
public bool IsComplexToolsVisible
{
get
{
return(ActiveDocViewModel != null && ActiveDocViewModel is DocComplexViewModel);
}
}
这绑定到工具箱该部分的 "Visibility"。同样,它按预期工作 - 但每当我们打开 DocSimple 时,它也会为复杂工具部分中的每个 属性 产生 "BindingExpression path error: 'xxx' property not found" 错误。通过向 DocSimple 添加 'stub' 属性来修复这些问题很容易,但这显然是错误的(使用继承将 "complex" 功能添加到 "simple" 基础有什么意义当我最终为基础 class 中的所有内容添加存根时键入?)。因此,这些绑定错误的存在让我质疑这种方法是否有缺陷 - 以及我如何在避免所有绑定错误的同时处理复杂与简单的场景。
任何见解将不胜感激:)
乍一看,总体结构在我看来非常好,但我不是专家,不想这样评价。
那么针对您的绑定错误问题: 您可以使用 TemplateSelector,它为 DocSimple 类型提供一个带有 "simple toolbox" 的模板和一个不同的模板,其中包含简单工具箱以及 DocComplex 的附加部分。