WPF随笔(十二)--使用MVVM模式

规模稍大的WPF项目一般会采用MVVM模式,常见的框架有Prism、MvvmLight、Caliburn等。今天就从头开始创建一个使用MVVM模式的WPF项目,对MVVM也能有一个更好的了解。


1.实现INotifyPropertyChanged接口

实现INotifyPropertyChanged接口是为了利用WPF的数据绑定特性,当数据源发生变化时,能及时通知UI层进行刷新,避免手动刷新UI的问题。

    public class ViewModelBase : INotifyPropertyChanged
    {

        #region INotifyPropertyChanged

        public event PropertyChangedEventHandler PropertyChanged;

        protected internal virtual void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
        #endregion

    }

2.实现ICommand接口

WPF默认的交互方式是事件驱动的,即UI层的动作触发路由事件,数据层在路由事件的函数中进行相应处理。实现ICommand接口是为了将UI层和数据层解耦,避免绑定路由事件时的强关联。

public class DelegateCommands<T> : ICommand
    {
        private readonly Action<T> _executeMethod = null;
        private readonly Func<T, bool> _canExecuteMethod = null;

        public DelegateCommands(Action<T> executeMethod)
            : this(executeMethod, null)
        { }

        public DelegateCommands(Action<T> executeMethod, Func<T, bool> canExecuteMethod)
        {
            if (executeMethod == null)
                throw new ArgumentNullException("executeMetnod");
            _executeMethod = executeMethod;
            _canExecuteMethod = canExecuteMethod;
        }

        #region ICommand 成员
        /// <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);
            }
        }

        #endregion


        event EventHandler ICommand.CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }

        #region ICommand 成员

        public bool CanExecute(object parameter)
        {
            if (parameter == null && typeof(T).IsValueType)
            {
                return (_canExecuteMethod == null);

            }

            return CanExecute((T)parameter);
        }

        public void Execute(object parameter)
        {
            Execute((T)parameter);
        }

        #endregion
    }

3.创建ViewModel

新建MainWindowViewModel类,继承自上面的ViewModelBase类,用于命令的绑定触发和数据的处理通知。

    public class MainWindowViewModel:ViewModelBase
    {
        public MainWindowViewModel()
        {
        	//命令绑定
            AddCommand = new DelegateCommands<string>(Add);
            EditCommand = new DelegateCommands<DetailGoodsDto>(Edit);
            DeleteCommand = new DelegateCommands<DetailGoodsDto>(Delete);
			//数据初始化
            InitData();
        }

        #region Properties-属性
        private List<DetailGoodsDto> _goodsList;

        public List<DetailGoodsDto> GoodsList
        {
            get { return _goodsList; }
            set
            {
                if (_goodsList != value)
                {
                    _goodsList = value;
                    OnPropertyChanged("GoodsList");
                }
            }
        }
        #endregion

        #region Commands-命令
        public DelegateCommands<string> AddCommand { get; set; }
        public DelegateCommands<DetailGoodsDto> EditCommand { get; set; }
        public DelegateCommands<DetailGoodsDto> DeleteCommand { get; set; }
        #endregion

        #region Methods-方法
        private void InitData()
        {
            GoodsList = new List<DetailGoodsDto>()
            {
            	new DetailGoodsDto
            	{
            		GoodsName="矿泉水",
            		GoodsType="酒水饮料",
            		Location="1号库",
            		GoodsNum=100
				}
			};
            
        }

        private void Add(string obj)
        {
        	//to do
        }

        private void Edit(DetailGoodsDto obj)
        {
            //to do
        }

        private void Delete(DetailGoodsDto obj)
        {
            //to do
        }
        #endregion

    }

4.修改View并绑定数据上下文

修改MainWindow.xaml,与MainWindowViewModel中的属性和命令一一对应。

<Window x:Class="AbpDemo.Client.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:AbpDemo.Client"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid Margin="5">
        <Grid.RowDefinitions>
            <RowDefinition Height="80"></RowDefinition>
            <RowDefinition></RowDefinition>
        </Grid.RowDefinitions>
        <WrapPanel Grid.Row="0" VerticalAlignment="Center" HorizontalAlignment="Right">
            <Button Command="{Binding AddCommand}" CommandParameter="Add">添加</Button>
            <Button Command="{Binding EditCommand}" CommandParameter="{Binding ElementName=GoodsData,Path=SelectedItem}">编辑</Button>
            <Button Command="{Binding DeleteCommand}" CommandParameter="{Binding ElementName=GoodsData,Path=SelectedItem}">删除</Button>
        </WrapPanel>
        <DataGrid x:Name="GoodsData" Grid.Row="1" AutoGenerateColumns="False" SelectionUnit="FullRow" ItemsSource="{Binding GoodsList}">
            <DataGrid.Columns>
                <DataGridTextColumn Header="货品名称" Width="*" Binding="{Binding GoodsName}"></DataGridTextColumn>
                <DataGridTextColumn Header="货品类型" Width="*" Binding="{Binding GoodsType}"></DataGridTextColumn>
                <DataGridTextColumn Header="存放位置" Width="*" Binding="{Binding Location}"></DataGridTextColumn>
                <DataGridTextColumn Header="货品数量" Width="*" Binding="{Binding GoodsNum}"></DataGridTextColumn>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>

同时修改MainWindow.xaml.cs以建立View视图层与ViewModel视图模型层的关联关系。

    public partial class MainWindow : Window
    {
        private MainWindowViewModel _viewModel;

        public MainWindow()
        {
            _viewModel = new MainWindowViewModel();
            this.DataContext = _viewModel;//设置数据上下文
            InitializeComponent();
        }
    }

以上步骤就完成了最简单的MVVM模式。


  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值