2010-10-05 51 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的,如果你用工作類型那不是那個階級的後裔。

相關問題