以下是概要的目录结构,其中View,ViewModel,Model正代表的是MVVM的标识。
View:页面window或者UserControl
Model:数据模型对象
ViewModel:与View交互binding,逻辑业务处理。
当然可以根据自己项目的具体情况,再进行拆分,包括业务逻辑,
服务数据分离,日志分离等。
其中主要的两个文件:
ViewModelBase.cs
ViewModel的绑定
using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Linq.Expressions; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows; using System.Windows.Threading; namespace Common { public abstract class ViewModelBase : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; public virtual void OnPropertyChanged(string propertyName) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } } public static class ViewModelBaseEx { public static void OnPropertyChanged<T, TProperty>(this T PropetyChangedBase, Expression<Func<T, TProperty>> propertyName) where T : ViewModelBase { var propertyNameExpression = propertyName.Body as MemberExpression; if (propertyNameExpression != null) { if (Dispatcher.CurrentDispatcher.Thread == Thread.CurrentThread) { PropetyChangedBase.OnPropertyChanged(propertyNameExpression.Member.Name); } else { Application.Current.Dispatcher.BeginInvoke(new Action(() => { PropetyChangedBase.OnPropertyChanged(propertyNameExpression.Member.Name); })); } } } } }
事件binding
DeletgateCommand.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Input; namespace Common { public class DelegateCommand : System.Windows.Input.ICommand { public DelegateCommand(Action executeMethod) : this(executeMethod, null, false) { } public DelegateCommand(Action executeMethod, Func<bool> canExecuteMethod) : this(executeMethod, canExecuteMethod, false) { } public DelegateCommand(Action executeMethod, Func<bool> canExecuteMethod, bool isAutomaticRequeryDisabled) { if (executeMethod == null) { throw new ArgumentNullException("executeMethod"); } _executeMethod = executeMethod; _canExecuteMethod = canExecuteMethod; _isAutomaticRequeryDisabled = isAutomaticRequeryDisabled; } public bool CanExecute() { if (_canExecuteMethod != null) { return _canExecuteMethod(); } return true; } public void Execute() { if (_executeMethod != null) { _executeMethod(); } } public bool IsAutomaticRequeryDisabled { get { return _isAutomaticRequeryDisabled; } set { if (_isAutomaticRequeryDisabled != value) { if (value) { CommandManagerHelper.RemoveHandlersFromRequerySuggested(_canExecuteChangedHandlers); } else { CommandManagerHelper.AddHandlersToRequerySuggested(_canExecuteChangedHandlers); } _isAutomaticRequeryDisabled = value; } } } public void RaiseCanExecuteChanged() { OnCanExecuteChanged(); } protected virtual void OnCanExecuteChanged() { CommandManagerHelper.CallWeakReferenceHandlers(_canExecuteChangedHandlers); } public event EventHandler CanExecuteChanged { add { if (!_isAutomaticRequeryDisabled) { CommandManager.RequerySuggested += value; } CommandManagerHelper.AddWeakReferenceHandler(ref _canExecuteChangedHandlers, value, 2); } remove { if (!_isAutomaticRequeryDisabled) { CommandManager.RequerySuggested -= value; } CommandManagerHelper.RemoveWeakReferenceHandler(_canExecuteChangedHandlers, value); } } bool System.Windows.Input.ICommand.CanExecute(object parameter) { return CanExecute(); } void System.Windows.Input.ICommand.Execute(object parameter) { Execute(); } private readonly Action _executeMethod = null; private readonly Func<bool> _canExecuteMethod = null; private bool _isAutomaticRequeryDisabled = false; private List<WeakReference> _canExecuteChangedHandlers; } public class DelegateCommand<T> : System.Windows.Input.ICommand { public DelegateCommand(Action<T> executeMethod) : this(executeMethod, null, false) { } public DelegateCommand(Action<T> executeMethod, Func<T, bool> canExecuteMethod) : this(executeMethod, canExecuteMethod, false) { } public DelegateCommand(Action<T> executeMethod, Func<T, bool> canExecuteMethod, bool isAutomaticRequeryDisabled) { if (executeMethod == null) { throw new ArgumentNullException("executeMethod"); } _executeMethod = executeMethod; _canExecuteMethod = canExecuteMethod; _isAutomaticRequeryDisabled = isAutomaticRequeryDisabled; } public bool CanExecute(T obj) { if (_canExecuteMethod != null) { return _canExecuteMethod(obj); } return true; } public void Execute(T obj) { if (_executeMethod != null) { _executeMethod(obj); } } public bool IsAutomaticRequeryDisabled { get { return _isAutomaticRequeryDisabled; } set { if (_isAutomaticRequeryDisabled != value) { if (value) { CommandManagerHelper.RemoveHandlersFromRequerySuggested(_canExecuteChangedHandlers); } else { CommandManagerHelper.AddHandlersToRequerySuggested(_canExecuteChangedHandlers); } _isAutomaticRequeryDisabled = value; } } } public void RaiseCanExecuteChanged() { OnCanExecuteChanged(); } protected virtual void OnCanExecuteChanged() { CommandManagerHelper.CallWeakReferenceHandlers(_canExecuteChangedHandlers); } public event EventHandler CanExecuteChanged { add { if (!_isAutomaticRequeryDisabled) { CommandManager.RequerySuggested += value; } CommandManagerHelper.AddWeakReferenceHandler(ref _canExecuteChangedHandlers, value, 2); } remove { if (!_isAutomaticRequeryDisabled) { CommandManager.RequerySuggested -= value; } CommandManagerHelper.RemoveWeakReferenceHandler(_canExecuteChangedHandlers, value); } } bool System.Windows.Input.ICommand.CanExecute(object parameter) { return CanExecute((T)parameter); } void System.Windows.Input.ICommand.Execute(object parameter) { Execute((T)parameter); } private readonly Action<T> _executeMethod = null; private readonly Func<T, bool> _canExecuteMethod = null; private bool _isAutomaticRequeryDisabled = false; private List<WeakReference> _canExecuteChangedHandlers; } //采用弱引用,避免内存泄漏 internal class CommandManagerHelper { internal static void CallWeakReferenceHandlers(List<WeakReference> handlers) { if (handlers != null) { // Take a snapshot of the handlers before we call out to them since the handlers // could cause the array to me modified while we are reading it. EventHandler[] callees = new EventHandler[handlers.Count]; int count = 0; for (int i = handlers.Count - 1; i >= 0; i--) { WeakReference reference = handlers[i]; EventHandler handler = reference.Target as EventHandler; if (handler == null) { // Clean up old handlers that have been collected handlers.RemoveAt(i); } else { callees[count] = handler; count++; } } // Call the handlers that we snapshotted for (int i = 0; i < count; i++) { EventHandler handler = callees[i]; handler(null, EventArgs.Empty); } } } internal static void AddHandlersToRequerySuggested(List<WeakReference> handlers) { if (handlers != null) { foreach (WeakReference handlerRef in handlers) { EventHandler handler = handlerRef.Target as EventHandler; if (handler != null) { CommandManager.RequerySuggested += handler; } } } } internal static void RemoveHandlersFromRequerySuggested(List<WeakReference> handlers) { if (handlers != null) { foreach (WeakReference handlerRef in handlers) { EventHandler handler = handlerRef.Target as EventHandler; if (handler != null) { CommandManager.RequerySuggested -= handler; } } } } internal static void AddWeakReferenceHandler(ref List<WeakReference> handlers, EventHandler handler) { AddWeakReferenceHandler(ref handlers, handler, -1); } internal static void AddWeakReferenceHandler(ref List<WeakReference> handlers, EventHandler handler, int defaultListSize) { if (handlers == null) { handlers = (defaultListSize > 0 ? new List<WeakReference>(defaultListSize) : new List<WeakReference>()); } handlers.Add(new WeakReference(handler)); } internal static void RemoveWeakReferenceHandler(List<WeakReference> handlers, EventHandler handler) { if (handlers != null) { for (int i = handlers.Count - 1; i >= 0; i--) { WeakReference reference = handlers[i]; EventHandler existingHandler = reference.Target as EventHandler; if ((existingHandler == null) || (existingHandler == handler)) { // Clean up old handlers that have been collected // in addition to the handler that is to be removed. handlers.RemoveAt(i); } } } } } }
这样基本的内容就齐了,简单的MVVM可以实现binding等功能了。