【问题标题】:AvalonDock MVVM dynamic viewAvalonDock MVVM 动态视图
【发布时间】:2019-05-07 13:29:31
【问题描述】:

我正在使用 Xceed.Wpf.AvalonDock 包(版本 3.5)中的 AvalonDock。对接管理器是我主要视图的一部分。有趣的部分在这里:

    <xcad:DockingManager Name="_dockingManager" Grid.Row="1" DataContext="{Binding DockingManagerViewModel}"
                     DocumentsSource="{Binding Documents}"
                     AnchorablesSource="{Binding Anchorables}" >

        <xcad:DockingManager.Resources>

            <DataTemplate DataType="{x:Type vm:DockingWindowViewModel}">
                <v:SampleDockWindowView />
            </DataTemplate>

        </xcad:DockingManager.Resources>

        <xcad:DockingManager.LayoutItemContainerStyle>
            <Style TargetType="{x:Type dockctrl:LayoutItem}" >
                <Setter Property="Title" Value="{Binding Model.Title}" />
                <Setter Property="CloseCommand" Value="{Binding Model.CloseCommand}" />
                <Setter Property="CanClose" Value="{Binding Model.CanClose}" />
            </Style>
        </xcad:DockingManager.LayoutItemContainerStyle>

    </xcad:DockingManager>

所以主视图模型包含一个可观察的集合(例如“文档”),我可以在其中动态添加视图模型。现在的问题是我对不同的视图模型有不同的视图,并且视图将在运行时添加。目前,视图是根据数据模板检索的:

    <xcad:DockingManager.Resources>

        <DataTemplate DataType="{x:Type vm:DockingWindowViewModel}">
            <v:SampleDockWindowView />
        </DataTemplate>

    </xcad:DockingManager.Resources>

如何更改此设置以获取基于相应视图模型的动态视图?

【问题讨论】:

  • 您可以使用DataTemplateSelector 来实现更复杂的模板选择逻辑。
  • @BradleyUffner:这并没有什么帮助。我不想做一个复杂的选择我想添加一个动态视图。不知道我是否理解正确
  • “复杂”的意思是“比在 XAML 中可以静态完成的更多”。您希望从运行时动态提供的模板列表中确定要显示的模板。您可以在运行时构建Dictionary&lt;Type, DataTemplate&gt;,用于将类型映射到模板,DataTemplateSelector 可以只返回为该类型注册的模板。这允许您在运行时添加/删除模板。

标签: c# mvvm prism avalondock


【解决方案1】:

正如一些人已经在这里回答的那样,您需要添加一个模板选择器。 所以一个例子可能会驱使你。

假设您有 2 对名为

的视图/视图模型

MyDocViewA -&gt; MyDocAViewModel

MyDocViewB -&gt; MyDocBViewModel

在主视图 XAML 代码中,在您的 DockingManager 代码中,您需要像这样添加 LayoutItemTemplateSelector

                <xcad:DockingManager.LayoutItemTemplateSelector>
                <s:PanesTemplateSelector>
                    <s:PanesTemplateSelector.MyDocViewATemplate>
                        <DataTemplate>
                            <p:MyDocViewA />
                        </DataTemplate>
                    </s:PanesTemplateSelector.MyDocViewATemplate>
                    <s:PanesTemplateSelector.MyDocViewBTemplate>
                        <DataTemplate>
                            <p:MyDocViewB />
                        </DataTemplate>
                    </s:PanesTemplateSelector.MyDocViewBTemplate>                        
            </xcad:DockingManager.LayoutItemTemplateSelector>

其中s 是您定义PanesTemplateSelector 的命名空间,如下所示:

    class PanesTemplateSelector : DataTemplateSelector
{
    public DataTemplate MyDocViewATemplate { get; set; }
    public DataTemplate MyDocViewBTemplate { get; set; }

    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        if (item is MyDocAViewModel)
            return MyDocViewATemplate;

        if (item is MyDocBViewModel)
            return MyDocViewBTemplate;
    }
}

假设MyDocAViewModel 是视图MyDocViewAViewModelMyDocBViewModel 是视图MyDocViewBViewModel

就是这样。现在您可以将MyDocAViewModelMyDocBViewModel 的实例添加到DockingManager 的可观察集合(例如“文档”)中,并将其分别绑定到MyDocViewAMyDocViewB

【讨论】:

    【解决方案2】:

    视图到视图模型通常是一对一的映射,因此只需从 xaml 或代码或两者的组合中添加大量 DataTemplates...(每个模块和代码中的 xaml模块初始化程序将模块的 ResourceDictionary 合并到应用程序的 ResourceDictionary 中)。

    【讨论】:

    • 也许 DataTemplate 不是处理这个问题的正确“工具”。有什么办法可以避免这种情况???
    • 如果您想为视图模型定义视图,数据模板是 工具。如果你不喜欢有很多单行数据模板,我建议你放弃你的用户控件,直接在数据模板中定义视图。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-29
    相关资源
    最近更新 更多