2010-10-05 50 views
1

我试图学习如何从视图模型中分离视图,同时使视图具有尽可能少或没有代码隐藏的功能。如何使用不同的查看模式进行xaml控制

我的控件在对象处于显示模式时有一个文本块,而当用户想要编辑该域时有一个文本框。在这两种情况下,这些控件都必须绑定到模型视图中的相同字符串,但根据视图模型的状态只应显示相应的字符串。以前,我只是将面板子代修改为代码隐藏中的新元素......但据我了解,我应该尝试在XAML中为视图进行所有更改。

我的viewmodel有一个bool表示它是否处于显示或编辑模式。有没有一种方法可以指定使用不同的模板,具体取决于该bool的值,但将它全部保存在XAML中?

+0

你为什么要这么做? 简而言之,“对XAML进行所有更改”的指导原则可能对您没有意义。我会提供一个代码示例,但如果它看起来比你完全理解的东西更加复杂或者更难以维护,那么你会对自己造成伤害。 – 2010-10-05 22:40:57

+0

我对WPF还比较陌生,正在习惯什么可以被认为是“最佳实践”......我看了一个教程,展示了WPF中的MVVM模式,其中出现的部分原因是背后的代码应该几乎被剥离...如果你做得对,你的视图应该几乎完全是XAML,并且你的ViewModel应该与视图代码分离...所以基本上我正在探索不同的方法来组合一个接口可能会根据用户输入而改变。 – tbischel 2010-10-05 23:21:37

+0

我知道他们在说什么。但是,我遇到的每位顾问都将这些事情放入实际实践中,对这一想法不可知论进行报道。在我看来,它的开发旨在促进将Expression Blend出售给非常大型组织中的混合设计师/开发团队。 也许这种做法最适合在这些地方以团队为基础的筒仓项目。但对于业务线应用程序,它可能是一个巨大的分心。 但是我会给它这么多,你会学习复杂的XAML标记。但不要相信,如果它是XAML,那不是代码。这都是代码。 – 2010-10-05 23:33:32

回答

3

有一种方法可以通过使用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,并将WindowUserControlDataContext分配给您的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> 

这里是我使用,注意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值。如果你想使用Commands来连接按钮,这是一个完全不同的主题。这是值得讨论的,但是为了简单起见:

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的,如果你用工作类型那不是那个阶级的后裔。

相关问题