193行代码构建轻量WPF MVVM

什么是 WPF Mvvm

使用WPF技术做开发,如果说不知道mvvm或不会mvvm总有一种会被鄙夷感觉,至于什么是wpf mvvm,呃,这个‘深刻’的话题,百度,必应,谷歌随便你啦。

怎么构建193行的轻量MVVM呢

在了解wpf mvvm 后,那么我们可以开始设计我们的轻量mvvm了

  1. NotifyPropertyBase ,实现了INotifyPropertyChanged(这是什么?呃,百必谷)接口,主要做为ViewModel和Model的基类;
  2. RelayCommand,实现ICommand接口,如果实在不好理解,就‘粗犷’的认为,这就是一个‘超级’事件;

如实现‘超级’事件功能:
1.RelayCommand,无参命令;
2.RelayCommand,带参命令;
3.RelayEventCommand,E->EventArgs事件命令,解决需要在View Model中获取事件参数功能;
4.RelayEventCommand<E,T>,E->EventArgs,T-Parameter事件带参命令,如果又想得到事件,又想从UI上取一个元素会来,这是一个好帮手

  1. CommandEventParameter,怎么把事件和参数传到View Model呢?没错就是这个家伙干的;
  2. IEventArgsIEventParameter<E, T> ,IEventArgs< E>这家伙,负责告诉VIewModel事件相关内容;IEventParameter<E, T>看,就是多了一个T,T就是参数嘛,所以这个家伙就是负责把事件相关对象和参数告诉给ViewModel;

贴代码咯

贴代码之前,你得取找一个dll库,有了它,mvvm才完整啊,‘System.Windows.Interactivity.dll’

真的只有193行

namespace WpfSimpleMvvm.Mvvm
{
    using System;
    using System.ComponentModel;
    using System.Runtime.CompilerServices;
    using System.Windows;
    using System.Windows.Input;
    using System.Windows.Interactivity;
    //ViewModel/Model
    public class NotifyPropertyBase : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        public void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    //Command
    public class RelayCommand : ICommand
    {
        private readonly Action _ExecuteMethod;
        private readonly Func<bool> _CanExecuteMethod;
#if Silverlight
        public event EventHandler CanExecuteChanged;
#else
        public event EventHandler CanExecuteChanged { add { CommandManager.RequerySuggested += value; } remove { CommandManager.RequerySuggested -= value; } }
#endif   
        public Boolean IsEnabled { get; set; }
        public Boolean AutoInvokeRequerySuggested { get; set; }
        internal RelayCommand() => this.IsEnabled = true;
        public RelayCommand(Action executeMethod, Func<bool> canExecuteMethod = null) : this()
        {
            _ExecuteMethod = executeMethod ?? throw new ArgumentNullException($"参数‘{nameof(executeMethod)}’不能为null");
            _CanExecuteMethod = canExecuteMethod;
        }
        public virtual bool CanExecute(object parameter)
        {
            if (IsEnabled)
            {
                if (_CanExecuteMethod != null)
                {
                    return _CanExecuteMethod.Invoke();
                }
            }
            return IsEnabled;
        }
        public virtual void Execute(object parameter)
        {
            if (CanExecute(parameter) == false) return;
            this._ExecuteMethod?.Invoke();
            if (this.AutoInvokeRequerySuggested) CommandManager.InvalidateRequerySuggested();
        }
        public static RelayCommand Create(Action executeMethod, Func<bool> canExecuteMethod = null) => new RelayCommand(executeMethod, canExecuteMethod);
        public static RelayCommand Create<T>(Action<T> executeMethod, Func<T, bool> canExecuteMethod = null) => new RelayCommand<T>(executeMethod, canExecuteMethod);
        public static RelayCommand CreateEvent<E>(Action<IEventParameter<E, Object>> executeMethod, Func<IEventParameter<E, Object>, bool> canExecuteMethod = null) => new RelayEventCommand<E>(executeMethod, canExecuteMethod);
        public static RelayCommand CreateEvent<E, T>(Action<IEventParameter<E, T>> executeMethod, Func<IEventParameter<E, T>, bool> canExecuteMethod = null) => new RelayEventCommand<E, T>(executeMethod, canExecuteMethod);
    }
    internal class RelayCommand<T> : RelayCommand
    {
        private readonly Action<T> _ExecuteMethod;
        private readonly Func<T, Boolean> _CanExecuteMethod;
        public RelayCommand(Action<T> executeMethod, Func<T, bool> canExecuteMethod = null) : base()
        {
            _ExecuteMethod = executeMethod ?? throw new ArgumentNullException($"参数‘{nameof(executeMethod)}’不能为null");
            _CanExecuteMethod = canExecuteMethod;
        }
        public override bool CanExecute(object parameter)
        {
            if (IsEnabled)
            {
                if (_CanExecuteMethod != null)
                {
                    return _CanExecuteMethod.Invoke(parameter is T ? (T)parameter : default(T));
                }
            }
            return IsEnabled;
        }
        public override void Execute(object parameter)
        {
            if (CanExecute(parameter))
            {
                _ExecuteMethod?.Invoke(parameter is T ? (T)parameter : default(T));
                if (AutoInvokeRequerySuggested) CommandManager.InvalidateRequerySuggested();
            }
        }
    }
    internal class RelayEventCommand<E, T> : RelayCommand
    {
        private readonly Action<IEventParameter<E, T>> _ExecuteMethod;
        private readonly Func<IEventParameter<E, T>, Boolean> _CanExecuteMethod;
        public RelayEventCommand(Action<IEventParameter<E, T>> executeMethod, Func<IEventParameter<E, T>, Boolean> canExecuteMethod = null) : base()
        {
            this._ExecuteMethod = executeMethod;
            this._CanExecuteMethod = canExecuteMethod;
        }
        public override bool CanExecute(object parameter)
        {
            if (IsEnabled)
            {
                if (_CanExecuteMethod != null)
                {
                    return _CanExecuteMethod.Invoke(parameter is IEventParameter<E, T> ? parameter as IEventParameter<E, T> : ConvertParameter(parameter));
                }
            }
            return IsEnabled;
        }
        public override void Execute(object parameter)
        {
            var _para = ConvertParameter(parameter);
            if (CanExecute(_para) == false) return;
            _ExecuteMethod.Invoke(_para);
            if (AutoInvokeRequerySuggested) CommandManager.InvalidateRequerySuggested();
        }
        private IEventParameter<E, T> ConvertParameter(object parameter)
        {
            if (parameter is IEventParameter<object, object> _para)
            {
                return EventParameter.Create<E, T>(_para.Sender, _para.EventArgs, _para.Parameter);
            }
            throw new Exception($"参数类型不匹配,请使用实现{typeof(IEventParameter<,>)}接口的实例做为参数");
        }
    }
    internal class RelayEventCommand<E> : RelayEventCommand<E, object>
    {
        public RelayEventCommand(Action<IEventParameter<E, Object>> executeMethod) : base(executeMethod, null) { }
        public RelayEventCommand(Action<IEventParameter<E, Object>> executeMethod, Func<IEventParameter<E, Object>, bool> canExecuteMethod) : base(executeMethod, canExecuteMethod) { }
    }
    //EventToCommand
    public interface IEventArgs<E>
    {
        object Sender { get; }
        E EventArgs { get; }
    }
    public interface IEventParameter<E, T> : IEventArgs<E>
    {
        T Parameter { get; }
    }
    internal class EventParameter
    {
        private class EventParameterImp<E, T> : IEventParameter<E, T>
        {
            public object Sender { get; set; }
            public E EventArgs { get; set; }
            public T Parameter { get; set; }
        }
        public static IEventParameter<E, T> Create<E, T>(object sender, object args, object parameter)
        {
            var result = new EventParameterImp<E, T>() { Sender = sender };
            if (args is E)
            {
                result.EventArgs = (E)args;
            }
            else
            {
                throw new Exception($"事件命令,事件参数类型转换失败。{args.GetType().FullName} 不能转换为 {typeof(E).FullName}");
            }
            if (parameter != null)
            {
                if (parameter is T)
                {
                    result.Parameter = (T)parameter;
                }
                else
                {
                    throw new Exception($"事件命令,自定义参数类型转换失败。{parameter.GetType().FullName} 不能转换为 {typeof(T).FullName}");
                }
            }
            return result;
        }
    }
    public class CommandEventParameter : TriggerAction<DependencyObject>
    {
        public static readonly DependencyProperty CommandProperty = DependencyProperty.Register(nameof(Command), typeof(RelayCommand), typeof(CommandEventParameter));
        public static readonly DependencyProperty ParameterProperty = DependencyProperty.Register(nameof(Parameter), typeof(object), typeof(CommandEventParameter));
        public RelayCommand Command { get => (RelayCommand)GetValue(CommandProperty); set => SetValue(CommandProperty, value); }
        public object Parameter { get => GetValue(ParameterProperty); set => SetValue(ParameterProperty, value); }
        protected override void Invoke(object eventArgs)
        {
            if (AssociatedObject != null)
            {
                if (Command?.GetType().Name.Contains("RelayEventCommand`") == true)
                {
                    Command.Execute(EventParameter.Create<object, object>(AssociatedObject, eventArgs, Parameter));
                }
                else
                {
                    throw new Exception($"无法使用的命令类型,命令类型不匹配,请使用‘{typeof(RelayEventCommand<,>).FullName}’类型");
                }
            }
        }
    }
}

怎么用呢,那么创建一个工程吧

工程结构

别忘了引用‘System.Windows.Interactivity.dll

工程截图

构建MVVM应用
1.MVVM-Model Person.cs 这个就是我们的Model了,也就是MVVM 中的M

在这里插入图片描述

2.MVVM-VIew MainWindowVIew 这个是View,就是 MVVM中V啦

既然是MVVM模式,那么MainWindowVIew.cs是可以不写任何代码的哦,所以我们只需要用MainWindowVIew.xam来构建我们的View就可了
在这里插入图片描述

示效果
在这里插入图片描述

3.MVVM-VIewModel MainWindowViewModel 这个是ViewModel,也即是MVVM中的VM

在这里插入图片描述

结尾

按一下F5看看效果吧

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值