How to switch between views using DataTemplate + Triggers

后端 未结 2 769
鱼传尺愫
鱼传尺愫 2020-12-29 17:14

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 clicki

相关标签:
2条回答
  • 2020-12-29 17:55

    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>
    
    0 讨论(0)
  • 2020-12-29 18:02

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

    0 讨论(0)
提交回复
热议问题