查看 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
{
/// <summary>
/// Occurs when a property value changes.
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Checks if a property already matches a desired value. Sets the property and
/// notifies listeners only when necessary.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="storage"></param>
/// <param name="value"></param>
/// <param name="propertyName"></param>
/// <returns></returns>
protected virtual bool SetProperty<T>(ref T storage,T value,[CallerMemberName] string propertyName=null)
{
if (EqualityComparer<T>.Default.Equals(storage, value)) return false;
storage = value;
RaisePropertyChanged(propertyName);
return true;
}
/// <summary>
/// Raises this object's PropertyChanged event.
/// </summary>
/// <param name="propertyName"></param>
protected void RaisePropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
通過SetProperty<T>泛型方法 可以接收任意型別的屬性,然后判斷屬性值是否發生變化,如果變化就觸發PropertyChanged事件,通知UI本屬性值已經發生改變,
查看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<bool> _canExecuteMethod;
/// <summary>
/// Creates a new instance of DelegateCommand with the Action to invoke on execution.
/// </summary>
/// <param name="executeMethod"></param>
public DelegateCommand(Action executeMethod)
: this(executeMethod, () => true)
{
}
/// <summary>
/// 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.
/// </summary>
/// <param name="executeMethod"></param>
/// <param name="canExecuteMethod"></param>
public DelegateCommand(Action executeMethod, Func<bool> canExecuteMethod)
{
if(executeMethod==null||canExecuteMethod==null)
throw new ArgumentNullException(nameof(executeMethod));
_executeMethod = executeMethod;
_canExecuteMethod = canExecuteMethod;
}
/// <summary>
/// Executes the command.
/// </summary>
/// <param name="parameter"></param>
public void Execute(object parameter)
{
_executeMethod();
}
/// <summary>
/// Determines if the command can be executed.
/// </summary>
/// <param name="parameter"></param>
/// <returns></returns>
public bool CanExecute(object parameter)
{
return _canExecuteMethod();
}
}
通過DelegateCommand建構式加載兩個委托(Action _executeMethod ,Func<bool> _canExecuteMethod),如果存在可以正常實作命令,這里ICommand的實作也是極簡模式,后面可以繼續擴展,
在ViewModel中使用NotifyObject和DelegateCommand
public class MainWindowViewModel:NotifyObject
{
/// <summary>
/// 輸入1
/// </summary>
private double _input1;
public double Input1
{
get => _input1;
set => SetProperty(ref _input1,value);
}
/// <summary>
/// 輸入2
/// </summary>
private double _input2;
public double Input2
{
get => _input2;
set => SetProperty(ref _input2, value);
}
/// <summary>
/// 結果
/// </summary>
private double _result;
public double Result
{
get => _result;
set => SetProperty(ref _result, value);
}
/// <summary>
/// 加法命令
/// </summary>
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框架,也是一個學習程序記錄,
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/247908.html
標籤:WPF
