C# II: Class ViewModelBase and RelayCommand in MVVM
好久不写WPF和MVVM,新建一个Project后,想起来ViewModelBase和RelayCommand没有。以下Code摘自MSDN上的Article:Patterns - WPF Apps With The Model-View-ViewModel Design Pattern中附带的示例代码:
Class ViewModelBase :
using System; using System.ComponentModel; using System.Diagnostics; namespace DemoApp.ViewModel { /// <summary> /// Base class for all ViewModel classes in the application. /// It provides support for property change notifications /// and has a DisplayName property. This class is abstract. /// </summary> public abstract class ViewModelBase : INotifyPropertyChanged, IDisposable { #region Constructor protected ViewModelBase() { } #endregion // Constructor #region DisplayName /// <summary> /// Returns the user-friendly name of this object. /// Child classes can set this property to a new value, /// or override it to determine the value on-demand. /// </summary> public virtual string DisplayName { get; protected set; } #endregion // DisplayName #region Debugging Aides /// <summary> /// Warns the developer if this object does not have /// a public property with the specified name. This /// method does not exist in a Release build. /// </summary> [Conditional("DEBUG")] [DebuggerStepThrough] public void VerifyPropertyName(string propertyName) { // Verify that the property name matches a real, // public, instance property on this object. if (TypeDescriptor.GetProperties(this)[propertyName] == null) { string msg = "Invalid property name: " + propertyName; if (this.ThrowOnInvalidPropertyName) throw new Exception(msg); else Debug.Fail(msg); } } /// <summary> /// Returns whether an exception is thrown, or if a Debug.Fail() is used /// when an invalid property name is passed to the VerifyPropertyName method. /// The default value is false, but subclasses used by unit tests might /// override this property's getter to return true. /// </summary> protected virtual bool ThrowOnInvalidPropertyName { get; private set; } #endregion // Debugging Aides #region INotifyPropertyChanged Members /// <summary> /// Raised when a property on this object has a new value. /// </summary> public event PropertyChangedEventHandler PropertyChanged; /// <summary> /// Raises this object's PropertyChanged event. /// </summary> /// <param name="propertyName">The property that has a new value.</param> protected virtual void OnPropertyChanged(string propertyName) { this.VerifyPropertyName(propertyName); PropertyChangedEventHandler handler = this.PropertyChanged; if (handler != null) { var e = new PropertyChangedEventArgs(propertyName); handler(this, e); } } #endregion // INotifyPropertyChanged Members #region IDisposable Members /// <summary> /// Invoked when this object is being removed from the application /// and will be subject to garbage collection. /// </summary> public void Dispose() { this.OnDispose(); } /// <summary> /// Child classes can override this method to perform /// clean-up logic, such as removing event handlers. /// </summary> protected virtual void OnDispose() { } #if DEBUG /// <summary> /// Useful for ensuring that ViewModel objects are properly garbage collected. /// </summary> ~ViewModelBase() { string msg = string.Format("{0} ({1}) ({2}) Finalized", this.GetType().Name, this.DisplayName, this.GetHashCode()); System.Diagnostics.Debug.WriteLine(msg); } #endif #endregion // IDisposable Members } }
Class RelayCommand:
using System; using System.Diagnostics; using System.Windows.Input; namespace DemoApp { /// <summary> /// A command whose sole purpose is to /// relay its functionality to other /// objects by invoking delegates. The /// default return value for the CanExecute /// method is 'true'. /// </summary> public class RelayCommand : ICommand { #region Fields readonly Action<object> _execute; readonly Predicate<object> _canExecute; #endregion // Fields #region Constructors /// <summary> /// Creates a new command that can always execute. /// </summary> /// <param name="execute">The execution logic.</param> public RelayCommand(Action<object> execute) : this(execute, null) { } /// <summary> /// Creates a new command. /// </summary> /// <param name="execute">The execution logic.</param> /// <param name="canExecute">The execution status logic.</param> public RelayCommand(Action<object> execute, Predicate<object> canExecute) { if (execute == null) throw new ArgumentNullException("execute"); _execute = execute; _canExecute = canExecute; } #endregion // Constructors #region ICommand Members [DebuggerStepThrough] public bool CanExecute(object parameter) { return _canExecute == null ? true : _canExecute(parameter); } public event EventHandler CanExecuteChanged { add { CommandManager.RequerySuggested += value; } remove { CommandManager.RequerySuggested -= value; } } public void Execute(object parameter) { _execute(parameter); } #endregion // ICommand Members } }
是为之记。
Alva Chien
2016.6.20
是为之记。
Alva Chien