查看 INotifyPropertyChanged 接口源码

namespace System.ComponentModel
{
    //
    // 摘要:
    //     Notifies clients that a property value has changed.
    public interface INotifyPropertyChanged
    {
        //
        // 摘要:
        //     Occurs when a property value changes.
        event PropertyChangedEventHandler PropertyChanged;
    }
}

INotifyPropertyChanged接口定义了一个属性改变处理事件,通知客户端这个属性值已经发生改变。

定义NotifyObject实现 INotifyPropertyChanged

    public class NotifyObject : INotifyPropertyChanged
    {
        ////// Occurs when a property value changes.
        ///public event PropertyChangedEventHandler PropertyChanged;

        ////// Checks if a property already matches a desired value. Sets the property and
        /// notifies listeners only when necessary.
        //////////////////protected virtual bool SetProperty(ref T storage,T value,[CallerMemberName] string propertyName=null)
        {
            if (EqualityComparer.Default.Equals(storage, value)) return false;

            storage = value;

            RaisePropertyChanged(propertyName);

            return true;
        }

        ////// Raises this object's PropertyChanged event.
        //////protected void RaisePropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }

通过SetProperty

查看ICommand源码

namespace System.Windows.Input
{
    //
    // 摘要:
    //     Defines a command.
    public interface ICommand
    {
        //
        // 摘要:
        //     Occurs when changes occur that affect whether or not the command should execute.
        event EventHandler CanExecuteChanged;

        //
        // 摘要:
        //     Defines the method that determines whether the command can execute in its current
        //     state.
        //
        // 参数:
        //   parameter:
        //     Data used by the command. If the command does not require data to be passed,
        //     this object can be set to null.
        //
        // 返回结果:
        //     true if this command can be executed; otherwise, false.
        bool CanExecute(object parameter);
        //
        // 摘要:
        //     Defines the method to be called when the command is invoked.
        //
        // 参数:
        //   parameter:
        //     Data used by the command. If the command does not require data to be passed,
        //     this object can be set to null.
        void Execute(object parameter);
    }
}

ICommand接口定义了一个普通的事件,和命令执行方法Execute()、命令是否可以执行方法CanExecute()

定义DelegateCommand实现 ICommand

public class DelegateCommand : ICommand
    {
        public event EventHandler CanExecuteChanged;
        private readonly Action _executeMethod;
        private readonly Func_canExecuteMethod;

        ////// Creates a new instance of DelegateCommand with the Action to invoke on execution.
        //////public DelegateCommand(Action executeMethod)
            : this(executeMethod, () => true)
        {

        }

        ////// Creates a new instance of DelegateCommand with the Action to invoke on execution
        /// and a Func to query for determining if the command can execute.
        /////////public DelegateCommand(Action executeMethod, FunccanExecuteMethod)
        {
            if(executeMethod==null||canExecuteMethod==null)
                throw  new ArgumentNullException(nameof(executeMethod));
            _executeMethod = executeMethod;
            _canExecuteMethod = canExecuteMethod;
        }

        ////// Executes the command.
        //////public void Execute(object parameter)
        {
            _executeMethod();
        }

        ////// Determines if the command can be executed.
        /////////public bool CanExecute(object parameter)
        {
            return _canExecuteMethod();
        }
    }

通过DelegateCommand构造函数加载两个委托(Action _executeMethod ,Func

在ViewModel中使用NotifyObject和DelegateCommand

    public class MainWindowViewModel:NotifyObject
    {
        ////// 输入1
        ///private double _input1;
        public double Input1
        {
            get => _input1;
            set => SetProperty(ref _input1,value);
        }

        ////// 输入2
        ///private double _input2;
        public double Input2
        {
            get => _input2;
            set => SetProperty(ref _input2, value);
        }

        ////// 结果
        ///private double _result;
        public double Result
        {
            get => _result;
            set => SetProperty(ref _result, value);
        }

        ////// 加法命令
        ///public DelegateCommand _addCommand;
        public DelegateCommand AddCommand => _addCommand ??= new DelegateCommand(Add);
        private  void Add()
        {
            Result = Input1+Input2;
        }
    }

在ViewModel 定义Input1 Input2 Result 跟View中的控件进行数据绑定,定义AddCommand跟View中事件拥有者绑定(命令绑定),当UI界面点击加法按钮,事件处理器就会响应这个命令执行Add()方法,完成运算。

总结:

通过上述接口实现,简单可以实现数据绑定和命令绑定,这个思路主要借鉴Prism框架,也是一个学习过程记录。