自定义Command动态关联按钮的是否起作用

  1. 场景分析
    • 正常的按钮触发(默认IsEnabled = true,点击即可触发)
    • ChechBoxIsChecked属性值是否为true来控制(勾选中按钮才能点击触发
    • TextBlockText属性值是否为空(Null or Empty)来控制(Length > 0才能点击触发)
  2. 两种方式动态控制
    1. 前台控制的方式
      <!-- 转换器 -->
      <cvt:StringIsEmptyOrNull x:Key="StringIsEmptyOrNull" />
      
      <StackPanel Orientation="Vertical">
          <CheckBox Name="CheckBoxIsEnable" 
          	IsChecked="{Binding CanExecute}" 
          	Content="允许点击按钮" Margin="5,5,5,0"/>
          <Button Content="可以禁止点击的按钮" Margin="5"
              Command="{Binding CanExecuteCommand}" />
          <Button Content="可以禁止点击的按钮(前台元素绑定控制显隐)" Margin="5" 
              IsEnabled="{Binding ElementName=CheckBoxIsEnable,Path=IsChecked}" />
          <DockPanel Margin="5,5,5,0">
              <TextBlock Text="输入参数:" VerticalAlignment="Center"/>
              <TextBox Name="ParamTextBox" DockPanel.Dock="Top" Margin="5"/>
          </DockPanel>
          <Button Content="带参数的按钮(前台元素绑定控制显隐)"  
              IsEnabled="{Binding ElementName=ParamTextBox, Path=Text,Converter={StaticResource StringIsEmptyOrNull}}" 
              Margin="5,0,5,5"/>
      </StackPanel>
      
      转换器
      public class StringIsEmptyOrNull:IValueConverter
      {
          public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
          {
              if (value == null || value.Equals(""))
              {
                  return false;
              }
              return true;
          }
      
          public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
          {
              return null;
          }
      }
      
      1.1 效果
      • 在这里插入图片描述

      • 在这里插入图片描述

    2. 后台控制的方式
      <StackPanel Orientation="Vertical">
          <CheckBox Name="CheckBoxIsEnable" 
          	IsChecked="{Binding CanExecute}" Content="允许点击按钮" Margin="5,5,5,0"/>
          <Button Content="可以禁止点击的按钮" Margin="5"
              Command="{Binding CanExecuteCommand}" />
          <TextBlock Text="输入参数:" VerticalAlignment="Center"/>
              <TextBox Name="ParamTextBox" DockPanel.Dock="Top" Margin="5"/>
          </DockPanel>
          <Button Content="带参数的按钮" 
              Command="{Binding ParamCommand}" 
              CommandParameter="{Binding ElementName=ParamTextBox, Path=Text}" 
              Margin="5,0,5,5"/>
      </StackPanel>
      
      2.1 效果
      • 在这里插入图片描述
      • -
  3. Mvvm全部代码
    • View
      1.1前台
      <Window x:Class="WPFDemo.StyleBindView.CustomCommandMainWindow"
              xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
              xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
              xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
              xmlns:local="clr-namespace:WPFDemo.StyleBindView"
              xmlns:cvt="clr-namespace:WPFDemo.Converts"
              mc:Ignorable="d"
              WindowStartupLocation="CenterScreen"
              Title="CustomCommandMainWindow" Height="450" Width="800">
          <Window.Resources>
              <ResourceDictionary>
                  <cvt:StringIsEmptyOrNull x:Key="StringIsEmptyOrNull" />
                  <ResourceDictionary.MergedDictionaries>
                      
                  </ResourceDictionary.MergedDictionaries>
                  
              </ResourceDictionary>
          </Window.Resources>
          <StackPanel Orientation="Vertical">
              <Button Content="普通按钮测试"  DockPanel.Dock="Top" Margin="5"
                      Command="{Binding NormalCommand}"/>
              <CheckBox Name="CheckBoxIsEnable" IsChecked="{Binding CanExecute}" Content="允许点击按钮" Margin="5,5,5,0"/>
              <Button Content="可以禁止点击的按钮" Margin="5"
                      Command="{Binding CanExecuteCommand}" />
              <Button Content="可以禁止点击的按钮(前台元素绑定控制显隐)" Margin="5" 
                      IsEnabled="{Binding ElementName=CheckBoxIsEnable,Path=IsChecked}" />
              <DockPanel Margin="5,5,5,0">
                  <TextBlock Text="输入参数:" VerticalAlignment="Center"/>
                  <TextBox Name="ParamTextBox" DockPanel.Dock="Top" Margin="5"/>
              </DockPanel>
              <Button Content="带参数的按钮" 
                      Command="{Binding ParamCommand}" 
                      CommandParameter="{Binding ElementName=ParamTextBox, Path=Text}" 
                      Margin="5,0,5,5"/>
              <Button Content="带参数的按钮(前台元素绑定控制显隐)"  
                      IsEnabled="{Binding ElementName=ParamTextBox, Path=Text,Converter={StaticResource StringIsEmptyOrNull}}" 
                      Margin="5,0,5,5"/>
          </StackPanel>
      </Window>
      
      1.2 后台
      /// <summary>
      /// CustomCommandMainWindow.xaml 的交互逻辑
      /// </summary>
      public partial class CustomCommandMainWindow : Window
      {
          public CustomCommandMainWindow()
          {
              InitializeComponent();
              this.DataContext = new CustomCommandViewModel();
          }
      }
      
    • Model
      public class CustomCommand : ICommand
      {
          #region 属性、字段
          /// <summary>
          /// 判断命令是否可以执行的方法
          /// </summary>
          private readonly Func<object, bool> _canExecute;
      
          /// <summary>
          /// 命令需要执行的方法
          /// </summary>
          private readonly Action<object> _execute;
          #endregion
      
          public CustomCommand(Action<object> execute, Func<object, bool> canExecute)
          {
              _execute = execute;
              _canExecute = canExecute;
          }
      
          public CustomCommand(Action<object> execute) : this(execute, null)
          {
          }
      
          #region 方法
          /// <summary>
          /// 检查命令是否可以执行的事件,在UI事件发生导致控件状态或数据发生变化时触发
          /// </summary>
          public event EventHandler CanExecuteChanged
          {
              add
              {
                  if (_canExecute != null)
                  {
                      CommandManager.RequerySuggested += value;
                  }
              }
              remove
              {
                  if (_canExecute != null)
                  {
                      CommandManager.RequerySuggested -= value;
                  }
              }
          }
      
          /// <summary>
          /// 判断命令是否是可执行
          /// </summary>
          /// <param name="parameter">命令传入的参数</param>
          /// <returns>是否可执行</returns>
          public bool CanExecute(object parameter)
          {
              if (_canExecute == null)
              {
                  return true;
              }
      
              return _canExecute(parameter);
          }
      
          /// <summary>
          /// 执行命令
          /// </summary>
          /// <param name="parameter">传入的参数/param>
          public void Execute(object parameter)
          {
              if (_execute != null && CanExecute(parameter))
              {
                  _execute(parameter);
              }
          }
          #endregion
      }
      
    • ViewModel
      [Description("https://www.cnblogs.com/durow/p/4858665.html")]
      public class CustomCommandViewModel : NotifyObject
      {
          #region 属性、字段
          #region 普通按钮
          private CustomCommand _normalCommand;
          public CustomCommand NormalCommand
          {
              set
              {
                  _normalCommand = value;
              }
              get
              {
                  //if (_normalCommand == null)
                  //{
                  //    _normalCommand = new CustomCommand(
                  //        new Action<object>(o => MessageBox.Show("这是个普通命令!"))
                  //        );
                  //}
                  return _normalCommand;
              }
          }
          #endregion
      
          private bool _canExecute;
          public bool CanExecute
          {
              get { return _canExecute; }
              set
              {
                  _canExecute = value;
                  OnRaisePropertyChanged("CanExecute");
              }
          }
      
          private CustomCommand _canExecuteCommand;
          public CustomCommand CanExecuteCommand
          {
              set
              {
                  _canExecuteCommand = value;
              }
              get
              {
                  //if (_canExecuteCommand == null)
                  //{ 
                  //    _canExecuteCommand = new CustomCommand(
                  //        new Action<object>(o => MessageBox.Show("命令可以执行!")),
                  //        new Func<object, bool>( o => CanExecute));
                  //}
                  return _canExecuteCommand;
              }
          }
      
          private CustomCommand _paramCommand;
          public CustomCommand ParamCommand
          {
              set
              {
                  _paramCommand = value;
              }
              get
              {
                  //if (_paramCommand == null)
                  //{ 
                  //    _paramCommand = new CustomCommand(
                  //        new Action<object>(o => MessageBox.Show(o.ToString())),
                  //        new Func<object, bool>(o => !string.IsNullOrEmpty(o.ToString())));
                  //}
                  return _paramCommand;
              }
          }
          #endregion
      
          public CustomCommandViewModel()
          {
              string pParmOne = "这是个普通命令!";
              //①NormalCommand = new CustomCommand(new Action<object>(CustomNormalMethod));
              NormalCommand = new CustomCommand(new Action<object>((object ss) => {
                  CustomNormalMethod(pParmOne);
              }));
      
              string pParmTwo = "命令可以执行!";
              CanExecuteCommand = new CustomCommand(
                  new Action<object>((object ss)=> {
                      CustomNormalMethod(pParmTwo);
                  }),
                  new Func<object, bool>(o => CanExecute));
      
              ParamCommand = new CustomCommand(
                  new Action<object>(o => CustomNormalMethod(o.ToString())),
                  new Func<object, bool>(o => !string.IsNullOrEmpty(Convert.ToString(o)))
                  );
          }
      
          #region 私有方法
          private void CustomNormalMethod(object pObj)
          {
              MessageBox.Show(pObj?.ToString());
          }
          #endregion
      }
      
      public class NotifyObject : INotifyPropertyChanged
      {
          public event PropertyChangedEventHandler PropertyChanged;
      
          public void OnRaisePropertyChanged(string propertyName)
          {
              PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
          }
          
          protected virtual void SetAndNotifIfChanged<T>(string propertyName, ref T oldValue,T newValue)
          {
              bool pConditionOne = (oldValue == null && newValue == null);
              bool pConditionTwo = (oldValue != null && oldValue.Equals(newValue));
              bool pConditionThree = (oldValue != null && oldValue.Equals(newValue));
              if (pConditionOne || pConditionTwo || pConditionThree)
              {
                  return;
              }
      
              oldValue = newValue;
              OnRaisePropertyChanged(propertyName);
          }
      }
      
  4. 参考
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

fengzhilu000

送人玫瑰,手留余香!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值