как сделать элемент управления xaml с разными режимами просмотра - PullRequest
1 голос
/ 06 октября 2010

Я пытаюсь научиться отделять представление от связанной с ним модели представления, в то же время заставляя представление иметь как можно меньше кода или вообще не иметь его.

В моем элементе управления есть текстовое поле, когда объект находится в режиме отображения, и текстовое поле, когда пользователь хочет изменить это поле. В обоих случаях эти элементы управления должны привязываться к одной и той же строке в представлении модели, но в зависимости от состояния модели представления должна отображаться только соответствующая строка. Раньше я просто модифицировал дочерний элемент Panel для нового элемента в коде позади ... но, насколько я понимаю, я должен пытаться внести все свои изменения в XAML для представления.

Моя модель представления имеет значение bool, обозначающее ее в режиме отображения или редактирования. Есть ли способ указать использование другого шаблона в зависимости от значения этого bool, но сохранить все это в XAML?

1 Ответ

3 голосов
/ 06 октября 2010

Есть способ сделать то, над чем вы работаете, используя DataTriggers.

Сначала определите Style, который содержит DataTrigger, которые вы хотите использовать. Например, обратите внимание, здесь два идентичных стиля для ContentControl, каждый с парой DataTrigger, которая выполняет противоположное другому:

<Window.Resources>
     <Style TargetType="{x:Type ContentControl}" x:Key="HiddenWhenFalse" >
        <Setter Property="Visibility" Value="Collapsed"/>
        <Style.Triggers>
            <DataTrigger  Value="False" Binding="{Binding MyBooleanValue}">
                <Setter Property="Visibility" Value="Collapsed" />
            </DataTrigger>
            <DataTrigger  Value="True" Binding="{Binding MyBooleanValue}">
                <Setter Property="Visibility" Value="Visible" />
            </DataTrigger>
        </Style.Triggers>
    </Style>


    <Style TargetType="{x:Type ContentControl}" x:Key="HiddenWhenTrue" >
        <Setter Property="Visibility" Value="Visible"/>
        <Style.Triggers>
            <DataTrigger  Value="True" Binding="{Binding MyBooleanValue}">
                <Setter Property="Visibility" Value="Collapsed" />
            </DataTrigger>
            <DataTrigger  Value="False" Binding="{Binding MyBooleanValue}">
                <Setter Property="Visibility" Value="Visible" />
            </DataTrigger>
        </Style.Triggers>
    </Style>
</Window.Resources>

Затем в вашем основном визуальном дереве вы определяете ContentControl s, которые используют эти Style s, и присваиваете DataContext из Window или UserControl или что-то еще для вашей ViewModel. Примерно так:

<Grid>
    <StackPanel >
        <Button Content="False" Name="Button2"></Button>
        <Button Content="True" Name="Button1"></Button>
        <ContentControl Style="{StaticResource HiddenWhenFalse}">
            <ContentControl.Content>
                <TextBlock Text="ITS ALL TRUE"/>
            </ContentControl.Content>
        </ContentControl>
        <ContentControl Style="{StaticResource HiddenWhenTrue}">
            <ContentControl.Content>
                <TextBlock Text="ITS ALL FALSE"/>
            </ContentControl.Content>
        </ContentControl>
    </StackPanel>
</Grid>

Вот ViewModel, который я использую, обратите внимание на реализацию INotifyPropertyChanged:

Imports System.ComponentModel

Public Class MainWindowViewModel
    Implements INotifyPropertyChanged
    Private _MyBooleanValue = False
    Public Property MyBooleanValue
        Get
            Return _MyBooleanValue
        End Get
        Set(ByVal value)
            _MyBooleanValue = value
            RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(Nothing))
        End Set
    End Property

    Public Event PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged
End Class

Теперь для целей этого примера я просто соединил две кнопки, чтобы установить значение ViewModel. Если вы хотите использовать Commanding для подключения кнопок, это совсем другая тема. Стоит обсудить, но ради простоты:

Class MainWindow 
    Private vm As New MainWindowViewModel
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles Button1.Click
        vm.MyBooleanValue = True
    End Sub

    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles Button2.Click
        vm.MyBooleanValue = False
    End Sub

    Private Sub MainWindow_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded
        Me.DataContext = vm
    End Sub
End Class

Имейте в виду, что этот образец явно стилизует ContentControl, и вам придется изменить TargetType вашего стиля, если вы работаете с типом, который не является потомком этого класса.

...