2017-04-14 22 views
0

我在MVVM和WPF是新的......在summerized形式 - 如何控制使用WPF和MVVM控制知名度diplay面板與零代碼點擊後面使用MVVM和WPF

問題。它也應該與零代碼背後。

實際情景-I有多個用戶控制面板...說UCPanel1,UCPanel2,UCPnale3 ...直到6 - 我在一個單一的主用戶控制導入這些用戶控件...說UCMain ,其具有頂部按鈕的堆棧面板...就像菜單一樣。 - 現在需求非常簡單...在button1上單擊 - 我應該可以看到UCPanel1和其餘面板隱藏,Button2單擊 - 我應該能夠看到UCPanel2和其餘面板隱藏...等等 - This i使用後面的代碼成功地獲得成功。但要求是實現這樣一種方式,即在代碼背後應儘可能少的代碼。 那麼我的XAML和視圖模型如何?
我無法訪問UCPanel1的擴展對象視圖模型..

在XAML的mainPanel ...

<Button 
    Style="{StaticResource StackPanelButtonStyle}" 
    Command="{Binding openMessageCommand}" > 
    <!--Click="BtnMessege_OnClick" >--> 
    <TextBlock 
     Text="Messaging" 
     Style="{StaticResource StackPanelButtonTextStyle}"> 
    </TextBlock> 
</Button> 
<Button 
    Style="{StaticResource StackPanelButtonStyle}" 
    Command="{Binding openProductsCommand}"> 
    <!--Click="BtnProducts_OnClick">--> 
    <TextBlock 
     Text="Products" 
     Style="{StaticResource StackPanelButtonTextStyle}" ></TextBlock> 
</Button> 

<local:StackPanelMessaging 
    Grid.Row="2" 
    Visibility="{Binding Panel1Visiblity}"></local:StackPanelMessaging> 
<local:WrapPanelProducts 
    Grid.Row="2" 
    Visibility="{Binding Panel2Visiblity}" ></local:WrapPanelProducts> 

在主視圖模型...

private Visibility _panel1Visiblity= Visibility.Visible; 
     private Visibility _panel2Visiblity= Visibility.Hidden; 


    public Visibility Panel1Visiblity 
     { 
      get { return _panel1Visiblity; } 
      set 
      { 
       if (_panel1Visiblity != value) 
       { 
        _panel1Visiblity = value; 
        OnPropertyChanged("Panel1Visiblity"); 
       } 
      } 
     } 
     public Visibility Panel2Visiblity 
     { 
      get { return _panel2Visiblity; } 
      set 
      { 
       if (_panel2Visiblity != value) 
       { 
        _panel2Visiblity = value; 
        OnPropertyChanged("Panel2Visiblity"); 
       } 
      } 
     } 

private void OpenStackMessagePanel() 
     { 
      Panel1Visiblity = Visibility.Visible; 
      Panel2Visiblity = Visibility.Hidden; 
     } 

     private bool canExecuteMethod1() 
     { 
      return true; 
     } 

     private void OpenWrapProductsPanel() 
     { 
      Panel2Visiblity = Visibility.Visible; 
      Panel1Visiblity = Visibility.Hidden; 
     } 

     private bool canExecuteMethod2() 
     { 
      return true; 
     } 
    public ICommand openMessageCommand 
     { 
      get 
      { 
       if (_openMessageCommand == null) 
       { 
        _openMessageCommand = new DelegateCommand(OpenStackMessagePanel, canExecuteMethod1, true); 
       } 
       return _openMessageCommand; 
      } 
     } 


     public ICommand openProductsCommand 
     { 
      get 
      { 
       if (_openProductsCommand == null) 
       { 
        _openProductsCommand = new DelegateCommand(OpenWrapProductsPanel, canExecuteMethod2, true); 
       } 
       return _openProductsCommand; 
      } 
     } 

而且我很感慨寫這麼多的代碼真的值得嗎?或者我應該優先考慮代碼後面只有10行....

+0

這是在一個視圖模型使用任何命令和可視性性能正常完成,或者如果這純粹是UI的觸發器添加到該按鈕來運行你的動畫面板可見屬性,故事板。 – kidshaw

+0

感謝您的回覆。是的,我做了同樣的事情,但不知道我錯在哪裏,面板在按鈕點擊時仍然沒有改變。請參閱編輯後的問題以獲取更多詳細信息...... – Lina

+0

不知道你會怎麼知道 - 你的面板沒有任何內容。首先添加斷點並證明您的視圖模型。 – kidshaw

回答

0

通過使用命令和可見性,你可以實現你想要的。這是一個簡單的例子。我沒有像你在做的那樣使用用戶控件,但是在這個例子中你應該明白這個想法。只需用您的用戶控件替換網格即可。

我要做的第一件事是創建一個BooleanToVisibilityConverter類。這是一個將布爾值轉換爲可見性的轉換器。我們不希望將可見性屬性放在我們的ViewModel中,因爲我們想要將UI與邏輯分開。所以我們在ViewModel中需要的是一個簡單的布爾值,它會告訴我們面板是否可見。

 public class BooleanToVisibilityConverter : IValueConverter 
     { 
     public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
     { 
      bool? boolValue = value as bool?; 
      return boolValue.HasValue && boolValue.Value ? Visibility.Visible : Visibility.Collapsed; 
     } 

     public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
     { 
      Visibility? visibilityValue = value as Visibility?; 
      return visibilityValue.HasValue && visibilityValue.Value == Visibility.Visible; 
     } 
     } 


Now in your MainViewModel class, you will have six boolean properties that will tell if your panel is visible or not. And then you will have 6 command properties that will set those boolean properties to true. 

    public class MainViewModel : BindableBase 
    { 
    private bool _IsPanel1Visible; 

    public bool IsPanel1Visible 
    { 
     get { return _IsPanel1Visible; } 
     set { SetProperty(ref _IsPanel1Visible, value); } 
    } 

    private bool _IsPanel2Visible; 

    public bool IsPanel2Visible 
    { 
     get { return _IsPanel2Visible; } 
     set { SetProperty(ref _IsPanel2Visible, value); } 
    } 

    private bool _IsPanel3Visible; 

    public bool IsPanel3Visible 
    { 
     get { return _IsPanel3Visible; } 
     set { SetProperty(ref _IsPanel3Visible, value); } 
    } 

    private bool _IsPanel4Visible; 

    public bool IsPanel4Visible 
    { 
     get { return _IsPanel4Visible; } 
     set { SetProperty(ref _IsPanel4Visible, value); } 
    } 

    private bool _IsPanel5Visible; 

    public bool IsPanel5Visible 
    { 
     get { return _IsPanel5Visible; } 
     set { SetProperty(ref _IsPanel5Visible, value); } 
    } 

    private bool _IsPanel6Visible; 

    public bool IsPanel6Visible 
    { 
     get { return _IsPanel6Visible; } 
     set { SetProperty(ref _IsPanel6Visible, value); } 
    } 

    public ICommand ShowPanel1Command { get { return new DelegateCommand(() => { HidePanels(); IsPanel1Visible = true; }); } } 
    public ICommand ShowPanel2Command { get { return new DelegateCommand(() => { HidePanels(); IsPanel2Visible = true; }); } } 
    public ICommand ShowPanel3Command { get { return new DelegateCommand(() => { HidePanels(); IsPanel3Visible = true; }); } } 
    public ICommand ShowPanel4Command { get { return new DelegateCommand(() => { HidePanels(); IsPanel4Visible = true; }); } } 
    public ICommand ShowPanel5Command { get { return new DelegateCommand(() => { HidePanels(); IsPanel5Visible = true; }); } } 
    public ICommand ShowPanel6Command { get { return new DelegateCommand(() => { HidePanels(); IsPanel6Visible = true; }); } } 

    private void HidePanels() 
    { 
     IsPanel1Visible = false; 
     IsPanel2Visible = false; 
     IsPanel3Visible = false; 
     IsPanel4Visible = false; 
     IsPanel5Visible = false; 
     IsPanel6Visible = false; 
    } 
    } 

現在在XAML中,你只需要綁定的布爾屬性面板的知名度和使用BooleanToVisibilityConverter爲布爾值轉換爲可見。而且您還需要將按鈕綁定到該命令。

<Grid> 
    <Grid.DataContext> 
     <local:MainViewModel /> 
    </Grid.DataContext> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="Auto" /> 
     <RowDefinition /> 
    </Grid.RowDefinitions> 
    <Grid.Resources> 
     <local:BooleanToVisibilityConverter x:Key="booleanToVisibilityConverter" /> 
    </Grid.Resources> 
    <StackPanel Orientation="Horizontal"> 
     <Button Content="Show Panel 1" Command="{Binding ShowPanel1Command}" /> 
     <Button Content="Show Panel 2" Command="{Binding ShowPanel2Command}" /> 
     <Button Content="Show Panel 3" Command="{Binding ShowPanel3Command}" /> 
     <Button Content="Show Panel 4" Command="{Binding ShowPanel4Command}" /> 
     <Button Content="Show Panel 5" Command="{Binding ShowPanel5Command}" /> 
     <Button Content="Show Panel 6" Command="{Binding ShowPanel6Command}" /> 
    </StackPanel> 
    <StackPanel Grid.Row="1"> 
     <Grid Visibility="{Binding IsPanel1Visible, UpdateSourcetrigger PropertyChanged, Converter={StaticResource booleanToVisibilityConverter}}"> 
     <TextBlock Text="Panel 1" /> 
     </Grid> 
     <Grid Visibility="{Binding IsPanel2Visible, UpdateSourcetrigger PropertyChanged, Converter={StaticResource booleanToVisibilityConverter}}"> 
     <TextBlock Text="Panel 2" /> 
     </Grid> 
     <Grid Visibility="{Binding IsPanel3Visible, UpdateSourcetrigger PropertyChanged, Converter={StaticResource booleanToVisibilityConverter}}"> 
     <TextBlock Text="Panel 3" /> 
     </Grid> 
     <Grid Visibility="{Binding IsPanel4Visible, UpdateSourcetrigger PropertyChanged, Converter={StaticResource booleanToVisibilityConverter}}"> 
     <TextBlock Text="Panel 4" /> 
     </Grid> 
     <Grid Visibility="{Binding IsPanel5Visible, UpdateSourcetrigger PropertyChanged, Converter={StaticResource booleanToVisibilityConverter}}"> 
     <TextBlock Text="Panel 5" /> 
     </Grid> 
     <Grid Visibility="{Binding IsPanel6Visible, UpdateSourcetrigger PropertyChanged, Converter={StaticResource booleanToVisibilityConverter}}"> 
     <TextBlock Text="Panel 6" /> 
     </Grid> 
    </StackPanel> 
    </Grid> 

更新:隱藏所有面板示出另一個之前。

你可以嘗試把這裏斷點來進行測試: enter image description here enter image description here

+0

令人驚歎!非常感謝...即使我使用了轉換器並找到了一個解決方案......但它有點不同。如果您覺得不合適,請隨時發表評論。 – Lina

+0

要求是...一旦一個面板可見,所有其他面板應該隱藏....我實現了這個解決方案,但多個面板是可見的同時,並沒有命令是擊中斷點..可能是我丟失了一些東西.. – Lina

+0

它應該在DelegateCommand的動作上達到一個斷點這就是斷點應該在的地方。這有點棘手,因爲你沒有把斷點放在那條線上。你可以去動作,然後按F9。我會更新解決方案以符合您的要求。 – Lance

0
<!--Button1--> 
      <Button Style="{StaticResource StackPanelButtonStyle}" Command="{Binding openPanelCommd}" CommandParameter="{Binding ElementName=WrapPanel1}" > 
       <TextBlock Text="1" Style="{StaticResource StackPanelButtonTextStyle}"> 
       </TextBlock>    
      </Button> 
      <!--Button2--> 
      <Button Style="{StaticResource StackPanelButtonStyle}" Command="{Binding openPanelCommd}" CommandParameter="{Binding ElementName=WrapPanel2}" > 
       <TextBlock Text="2" Style="{StaticResource StackPanelButtonTextStyle}"></TextBlock> 
       </Button> 
      <!--Button3--> 
      <Button Style="{StaticResource StackPanelButtonStyle}" Command="{Binding openPanelCommd}" CommandParameter="{Binding ElementName=WrapPanel3}" > 
       <TextBlock Text="3" Style="{StaticResource StackPanelButtonTextStyle}" ></TextBlock> 
      </Button> 
      <!--Button4--> 
      <Button Style="{StaticResource StackPanelButtonStyle}" Command="{Binding openPanelCommd}" CommandParameter="{Binding ElementName=WrapPanel4}" > 
       <TextBlock Text="4" Style="{StaticResource StackPanelButtonTextStyle}" ></TextBlock> 
       </Button> 
      <!--Button5--> 
      <Button Style="{StaticResource StackPanelButtonStyle}" Command="{Binding openPanelCommd}" CommandParameter="{Binding ElementName=WrapPanel5}" > 
       <TextBlock Text="5" Style="{StaticResource StackPanelButtonTextStyle}"></TextBlock> 
       </Button> 
    <!--Panels--> 
     <local:WrapPanelProducts x:Name="WrapPanel1" Grid.Row="2" 
       Visibility="Collapsed"/> 
    <local:WrapPanelProducts x:Name="WrapPanel2" Grid.Row="2" 
      Visibility="Collapsed"/> 
    <local:WrapPanelProducts x:Name="WrapPanel3" Grid.Row="2" 
      Visibility="Collapsed"/> 
    <local:WrapPanelProducts x:Name="WrapPanel4" Grid.Row="2" 
      Visibility="Collapsed"/> 
    <local:WrapPanelProducts x:Name="WrapPanel5" Grid.Row="2" 
      Visibility="Collapsed"/> 

代碼背後,是

public StackPanelMain() 
     { 

      InitializeComponent();    
      StackPanelMainViewModel StackPanelMainViewModel1 = new StackPanelMainViewModel(); 
      this.DataContext = StackPanelMainViewModel1; 

     } 

和視圖模型代碼如下...

public RelayCommand openPanelCommd { get; set; } 

    //Constructor 
     public StackPanelMainViewModel() 
     { 
      openPanelCommd = new RelayCommand(OpenPanel); 
     } 


    private void OpenPanel(object parameter) 
{ 
    var args = (object) parameter; 

    var elementname = (UIElement) args; 

    elementname.Visibility = Visibility.Visible; 

} 
+0

這應該工作,但這個想法是沒有任何虛擬機中的UI對象。它擊敗了MVVM的目的。虛擬機應該不知道用戶界面。 – Lance

+0

完全同意.. – Lina