-
场景分析
-
两种方式动态控制
-
前台控制的方式
转换器<!-- 转换器 --> <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 效果
-
后台控制的方式
<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 效果
-
-
Mvvm全部代码
View
1.1前台
1.2 后台<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>
/// <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); } }
-
参考