How to switch between views using DataTemplate + Triggers

|▌冷眼眸甩不掉的悲伤 提交于 2019-11-29 04:17:02

问题


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.


回答1:


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}.




回答2:


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>


来源:https://stackoverflow.com/questions/6546436/how-to-switch-between-views-using-datatemplate-triggers

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!