Mvvm模式学习
mvvm模式.先让xaml页面与xaml.cs分离。
原来是双击button生成个事件,添加代码,按钮的功能完成。要使页面与代码分离,最起码得把button事件的处理代码从xaml.cs文件中弄出去吧。
原来是直接双击,后台生成。现在不能双击了。麻烦但是有用。不经革命之痛苦,怎得革命之幸福。
找个代码,改改理解理解吧。发现要实现点击得数据绑定。
<Button Content="Button" HorizontalAlignment="Left" VerticalAlignment="Top" Command="{Binding Path=ShowCommand}" Width="75" Margin="331,224,0,0"/>
既然是绑定就得有数据上下文。查找发现有
<Grid.DataContext>
<local:ShowViewModel />
</Grid.DataContext>
那么就得有xmlns:local="clr-namespace:mccmlearn.ViewModel"
页面代码:
<Window x:Class="mccmlearn.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:mccmlearn.ViewModel" Title="MainWindow" Height="350" Width="525"> <Grid> <Grid.DataContext> <local:ShowViewModel /> </Grid.DataContext> <Button Content="Button" HorizontalAlignment="Left" VerticalAlignment="Top" Command="{Binding Path=ShowCommand}" Width="75" Margin="331,224,0,0"/> </Grid> </Window>
后台代码不用贴了因为什么也没有。
这是项目结构,看viewmodel中的ShowViewModel.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Input; using mccmlearn.Commands; namespace mccmlearn.ViewModel { internal class ShowViewModel { private DelegateCommand showCommand; public ICommand ShowCommand { get { if (showCommand == null) showCommand = new DelegateCommand(new Action(ShowExecuted), new Func<bool>(ShowCanExecute)); return showCommand; } } private bool ShowCanExecute() { return true; } private void ShowExecuted() { System.Windows.MessageBox.Show("dd"); } } }
下面是DelegateCommand类,从网上找的,
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows.Input; namespace mccmlearn.Commands { /// <summary> /// This class allows delegating the commanding logic to methods passed as parameters, /// and enables a View to bind commands to objects that are not part of the element tree. /// </summary> public class DelegateCommand : ICommand { #region Constructors /// <summary> /// Constructor /// </summary> public DelegateCommand(Action executeMethod) : this(executeMethod, null, false) { } /// <summary> /// Constructor /// </summary> public DelegateCommand(Action executeMethod, Func<bool> canExecuteMethod) : this(executeMethod, canExecuteMethod, false) { } /// <summary> /// Constructor /// </summary> public DelegateCommand(Action executeMethod, Func<bool> canExecuteMethod, bool isAutomaticRequeryDisabled) { if (executeMethod == null) { throw new ArgumentNullException("executeMethod"); } _executeMethod = executeMethod; _canExecuteMethod = canExecuteMethod; _isAutomaticRequeryDisabled = isAutomaticRequeryDisabled; } #endregion #region Public Methods /// <summary> /// Method to determine if the command can be executed /// </summary> public bool CanExecute() { if (_canExecuteMethod != null) { return _canExecuteMethod(); } return true; } /// <summary> /// Execution of the command /// </summary> public void Execute() { if (_executeMethod != null) { _executeMethod(); } } /// <summary> /// Property to enable or disable CommandManager's automatic requery on this command /// </summary> public bool IsAutomaticRequeryDisabled { get { return _isAutomaticRequeryDisabled; } set { if (_isAutomaticRequeryDisabled != value) { if (value) { CommandManagerHelper.RemoveHandlersFromRequerySuggested(_canExecuteChangedHandlers); } else { CommandManagerHelper.AddHandlersToRequerySuggested(_canExecuteChangedHandlers); } _isAutomaticRequeryDisabled = value; } } } /// <summary> /// Raises the CanExecuteChaged event /// </summary> public void RaiseCanExecuteChanged() { OnCanExecuteChanged(); } /// <summary> /// Protected virtual method to raise CanExecuteChanged event /// </summary> protected virtual void OnCanExecuteChanged() { CommandManagerHelper.CallWeakReferenceHandlers(_canExecuteChangedHandlers); } #endregion #region ICommand Members /// <summary> /// ICommand.CanExecuteChanged implementation /// </summary> 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 ICommand.CanExecute(object parameter) { return CanExecute(); } void ICommand.Execute(object parameter) { Execute(); } #endregion #region Data private readonly Action _executeMethod = null; private readonly Func<bool> _canExecuteMethod = null; private bool _isAutomaticRequeryDisabled = false; private List<WeakReference> _canExecuteChangedHandlers; #endregion } /// <summary> /// This class allows delegating the commanding logic to methods passed as parameters, /// and enables a View to bind commands to objects that are not part of the element tree. /// </summary> /// <typeparam name="T">Type of the parameter passed to the delegates</typeparam> public class DelegateCommand<T> : ICommand { #region Constructors /// <summary> /// Constructor /// </summary> public DelegateCommand(Action<T> executeMethod) : this(executeMethod, null, false) { } /// <summary> /// Constructor /// </summary> public DelegateCommand(Action<T> executeMethod, Func<T, bool> canExecuteMethod) : this(executeMethod, canExecuteMethod, false) { } /// <summary> /// Constructor /// </summary> public DelegateCommand(Action<T> executeMethod, Func<T, bool> canExecuteMethod, bool isAutomaticRequeryDisabled) { if (executeMethod == null) { throw new ArgumentNullException("executeMethod"); } _executeMethod = executeMethod; _canExecuteMethod = canExecuteMethod; _isAutomaticRequeryDisabled = isAutomaticRequeryDisabled; } #endregion #region Public Methods /// <summary> /// Method to determine if the command can be executed /// </summary> public bool CanExecute(T parameter) { if (_canExecuteMethod != null) { return _canExecuteMethod(parameter); } return true; } /// <summary> /// Execution of the command /// </summary> public void Execute(T parameter) { if (_executeMethod != null) { _executeMethod(parameter); } } /// <summary> /// Raises the CanExecuteChaged event /// </summary> public void RaiseCanExecuteChanged() { OnCanExecuteChanged(); } /// <summary> /// Protected virtual method to raise CanExecuteChanged event /// </summary> protected virtual void OnCanExecuteChanged() { CommandManagerHelper.CallWeakReferenceHandlers(_canExecuteChangedHandlers); } /// <summary> /// Property to enable or disable CommandManager's automatic requery on this command /// </summary> public bool IsAutomaticRequeryDisabled { get { return _isAutomaticRequeryDisabled; } set { if (_isAutomaticRequeryDisabled != value) { if (value) { CommandManagerHelper.RemoveHandlersFromRequerySuggested(_canExecuteChangedHandlers); } else { CommandManagerHelper.AddHandlersToRequerySuggested(_canExecuteChangedHandlers); } _isAutomaticRequeryDisabled = value; } } } #endregion #region ICommand Members /// <summary> /// ICommand.CanExecuteChanged implementation /// </summary> 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 ICommand.CanExecute(object parameter) { // if T is of value type and the parameter is not // set yet, then return false if CanExecute delegate // exists, else return true if (parameter == null && typeof(T).IsValueType) { return (_canExecuteMethod == null); } return CanExecute((T)parameter); } void ICommand.Execute(object parameter) { Execute((T)parameter); } #endregion #region Data private readonly Action<T> _executeMethod = null; private readonly Func<T, bool> _canExecuteMethod = null; private bool _isAutomaticRequeryDisabled = false; private List<WeakReference> _canExecuteChangedHandlers; #endregion } /// <summary> /// This class contains methods for the CommandManager that help avoid memory leaks by /// using weak references. /// </summary> 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); } } } } } }
这样就实现了按钮的事件,没有写在.xaml.cs里面。