Как переключаться между представлениями с помощью DataTemplate + триггеры - PullRequest
1 голос
/ 01 июля 2011

У меня есть требование, когда пользователь может переключаться, чтобы просматривать иерархические данные в виде дерева или текста в сетке данных или в виде FlowChart.

Пользователь может сделать это, нажав кнопку переключения, которая говорит: Переключить режим.Я хочу сделать все это таким образом, чтобы он мог обрабатываться в представлении только как ViewModel во всех трех случаях одинаково.

Как применить View к моей ViewModel на основе Trigger.*

Ответы [ 2 ]

13 голосов
/ 01 июля 2011

Если состояние отображаемого представления сохраняется в некотором свойстве enum, вы можете использовать ContentControl и DataTriggers, например:

<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 необходимо установить на что-то для применения шаблона))

Youможет также связываться непосредственно с IsChecked из ToggleButton, используя, конечно, ElementName.Соответствующие значения будут тогда True, False и {x:Null}.

0 голосов
/ 01 июля 2011

Х.Б. ответ хороший, но есть сценарии, в которых он не так хорош.

Если создание представлений (и их базовых моделей представлений) является дорогостоящим, то переключение свойства Content будет оплачивать эти расходы каждый раз, когда пользователь изменяет представление.

В некоторых сценариях имеет смысл создать оба представления в одном контейнере (например, Grid) и вместо этого переключать их Visibility. Если вы используете ленивую оценку в своих моделях представления, дорогостоящие операции не будут выполняться, пока представление не станет видимым, и, что важно, они будут выполняться только в первый раз, когда представление станет видимым. После отображения обоих представлений пользователь может переключаться между представлениями, не восстанавливая модели базовых представлений.

Изменить:

Я исправлен, вроде: ответ Х.Б. не так хорош, как выглядел.

Вы не можете использовать стиль, чтобы установить для свойства Content ContentControl значение UIElement. См. в этом блоге для получения полной информации, но, если кратко, то, если вы используете подход H.B., вы получите ошибку времени выполнения.

Вместо этого вы можете установить свойство 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>
...