如何使用 DataTemplate 在视图之间切换触发器

发布于 2024-11-18 10:08:31 字数 169 浏览 3 评论 0原文

我有一个要求,其中用户可以切换以树或数据网格中的文本或流程图的形式查看分层数据。

用户可以通过单击切换按钮来完成此操作,该按钮显示:切换模式。我想以这样一种方式来完成这一切,即它只能在视图中处理,因为所有三种情况下的 ViewModel 都是相同的。

如何基于触发器将视图应用到我的视图模型。

I have a requirement where a where user can switch to view hierarchical data either as tree or as a text in datagrid or as FlowChart.

The user can do this by clicking a Toggle Button which say: Switch Mode. I want to do all this in such a way that it can be handled within the View only as ViewModel in all the three cases is the same.

How do I apply View to my ViewModel based on Trigger.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

黑凤梨 2024-11-25 10:08:31

如果要显示的视图的状态保存在某个枚举属性中,您可以使用 ContentControlDataTriggers 例如:(

<ContentControl>
    <ContentControl.Style>
        <Style TargetType="{x:Type ContentControl}">
            <Style.Triggers>
                <DataTrigger Binding="{Binding ViewMode}" Value="TreeMode">
                    <Setter Property="Content">
                        <Setter.Value>
                            <uc:TreeModeView />
                        </Setter.Value>
                    </Setter>
                </DataTrigger>
                <DataTrigger Binding="{Binding ViewMode}" Value="GridMode">
                    <Setter Property="Content">
                        <Setter.Value>
                            <uc:GridModeView />
                        </Setter.Value>
                    </Setter>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </ContentControl.Style>
</ContentControl>

由于该样式仅在一处使用,因此直接将其设置为 ContentControl.Style 即可,如果你想在多个地方使用它,你应该设置 ContentTemplate 来代替,因为否则只有一个视图实例被所有控件共享,其样式是 WPF 不允许的(例如课程 Content 需要设置为要应用的模板的某些内容))

您还可以使用 ElementName 当然。相关值将为 TrueFalse{x:Null}

If the state of which view to show is saved in some enum property you could use a ContentControl and DataTriggers for example:

<ContentControl>
    <ContentControl.Style>
        <Style TargetType="{x:Type ContentControl}">
            <Style.Triggers>
                <DataTrigger Binding="{Binding ViewMode}" Value="TreeMode">
                    <Setter Property="Content">
                        <Setter.Value>
                            <uc:TreeModeView />
                        </Setter.Value>
                    </Setter>
                </DataTrigger>
                <DataTrigger Binding="{Binding ViewMode}" Value="GridMode">
                    <Setter Property="Content">
                        <Setter.Value>
                            <uc:GridModeView />
                        </Setter.Value>
                    </Setter>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </ContentControl.Style>
</ContentControl>

(As the style is only used in one place, by setting it directly as ContentControl.Style this will work, if you want to use it in more than one place you should set the ContentTemplate instead, because otherwise there will only be one view instance shared by all controls with the style which is not allowed by WPF (of course Content needs to be set to something for the template to be applied))

You could also bind directly to IsChecked of the ToggleButton using ElementName of course. The relevant values would then be True, False and {x:Null}.

薄凉少年不暖心 2024-11-25 10:08:31

HB 的答案很好,但有些情况下不太好。

如果构建视图(及其底层视图模型)的成本很高,那么每次用户更改视图时切换 Content 属性都会付出这笔费用。

在某些情况下,在同一个容器(例如Grid)中创建两个视图并切换它们的Visibility 是有意义的。如果您在视图模型中使用惰性求值,则在视图变得可见之前不会执行昂贵的操作,而且重要的是,它们只会在视图第一次可见时执行。一旦显示了两个视图,用户就可以在视图之间来回切换,而无需重建底层视图模型。

编辑:

我纠正了,有点:HB的答案并不像看起来那么好。

您无法使用样式将 ContentControlContent 属性设置为 UIElement。请参阅此博客发布以获取完整的详细信息,但总而言之,如果您使用 HB 的方法,您将收到运行时错误。

您可以改为设置 ContentTemplate 属性,例如:

<Style TargetType="{x:Type ContentControl}">
    <Style.Triggers>
        <DataTrigger Binding="{Binding ViewMode}"
                        Value="TreeMode">
            <Setter Property="ContentTemplate">
                <Setter.Value>
                    <DataTemplate>
                        <uc:TreeModeView/>
                    </DataTemplate>
                </Setter.Value>
            </Setter>
        </DataTrigger>
        <DataTrigger Binding="{Binding ViewMode}"
                        Value="GridMode">
            <Setter Property="ContentTemplate">
                <Setter.Value>
                    <DataTemplate>
                        <uc:GridModeView/>
                    </DataTemplate>
                </Setter.Value>
            </Setter>
        </DataTrigger>
    </Style.Triggers>
</Style>

H.B.'s answer is good, but there are scenarios where it's not quite so good.

If constructing the views (and their underlying view models) is expensive, then toggling the Content property will pay this expense every time the user changes the view.

In some scenarios, it makes sense to create both views in the same container (e.g. a Grid), and toggle their Visibility instead. If you use lazy evaluation in your view models, the expensive operations won't be conducted until the view becomes visible, and - importantly - they'll only be conducted the first time the view becomes visible. Once both views have been displayed, the user can toggle back and forth between views without reconstructing the underlying view models.

Edit:

I stand corrected, sort of: H.B.'s answer is not as good as it looked .

You can't use a style to set the Content property of a ContentControl to a UIElement. See this blog post for full details, but the long and short of it is that if you use H.B.'s approach, you'll get a runtime error.

You can set the ContentTemplate property, instead, e.g.:

<Style TargetType="{x:Type ContentControl}">
    <Style.Triggers>
        <DataTrigger Binding="{Binding ViewMode}"
                        Value="TreeMode">
            <Setter Property="ContentTemplate">
                <Setter.Value>
                    <DataTemplate>
                        <uc:TreeModeView/>
                    </DataTemplate>
                </Setter.Value>
            </Setter>
        </DataTrigger>
        <DataTrigger Binding="{Binding ViewMode}"
                        Value="GridMode">
            <Setter Property="ContentTemplate">
                <Setter.Value>
                    <DataTemplate>
                        <uc:GridModeView/>
                    </DataTemplate>
                </Setter.Value>
            </Setter>
        </DataTrigger>
    </Style.Triggers>
</Style>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文