按钮上的diplay面板使用mvvm和wpf单击后面的零代码

时间:2017-04-14 19:32:41

标签: wpf xaml mvvm data-binding viewmodel

我是MVVM和wpf的新手......

总结形式的问题 - 如何使用wpf和MVVM控制控件的可见性。它也应该零代码。

实际场景 - 我有多个用户控制面板...说UCPanel1,UCPanel2,UCPnale3 ...直到6 - 我在一个主用户控件中导入这些用户控件...说UCMain 它有堆叠面板,顶部有按钮......就像菜单一样。 - 现在要求非常简单......在按钮1点击 - 我应该能够看到UCPanel1和剩余的面板隐藏,Button2点击 - 我应该能够看到UCPanel2和剩余的面板隐藏......等等 - 这成功地使用了背后的代码。但要求是实现这样一种方式,即在代码背后应尽可能少的代码。 那我的XAML和视图模型怎么样? 我无法在viewmodel中访问UCPanel1的扩展对象..

在MainPanel XAML中......

<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行的代码......

2 个答案:

答案 0 :(得分:0)

通过使用命令和可见性,您可以实现您想要的效果。这是一个简单的例子。我没有像你一样使用用户控件,但是通过这个例子,你应该明白这个想法。只需用您的用户控件替换网格即可。

我要做的第一件事是创建一个BooleanToVisibilityConverter类。这是一个将布尔值转换为可见性的转换器。我们不希望将Visibility属性放在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

答案 1 :(得分: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"/>

Code Behind是

  public StackPanelMain()
        {

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

        }

和View型号代码如下......

 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;

 }