WPF使用MVVM完成DataGrid数据绑定带全选

先看看效果:
这里写图片描述
完全采用MVVM的各种绑定。点击表头CheckBox可实现全选和取消全选,选中数据行所有CheckBox时自动选中表头CheckBox,数据行中有未选中的则不会选中表头CheckBox。
这里写图片描述

demo下载:百度网盘(链接:https://pan.baidu.com/s/1vKmPFMbY6WSN6d0-kvu83w 密码:vk4h)


分割线,想直接看demo的就不需要看下面的代码了,以下是详细的代码及说明。


1. 构造MVVM基本功能类

因为没有使用MVVM框架,所以需要自己构造两个MVVM中的基本功能类,完成属性通知和命令绑定功能。

1.1 属性通知

    /// <summary>
    /// INotifyPropertyChanged 用于通知属性改变(实现ViewModel向View喊话,所有绑定该属性的都会得到通知)
    /// </summary>
    public class NotificationObject : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;


        /// <summary>
        /// 属性改变时调用该方法发出通知
        /// </summary>
        /// <param name="propertyName">[CallerMemberName] 是.net 4.5的新特性,可获取调用者的名称</param>
        public void RaisePropertyChanged([CallerMemberName]string propertyName = "")
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }

1.2 命令

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

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

        public DelegateCommand(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
    }

2. 构造Model、ViewModel

    public class Person
    {
        public int ID { get; set; }
        public string Name { get; set; }
    }

    public class PersonModel : NotificationObject
    {
        private bool _IsSelected = false;

        /// <summary>
        /// 是否选中
        /// </summary>
        public bool IsSelected
        {
            get
            {
                return _IsSelected;
            }
            set
            {
                _IsSelected = value;
                this.RaisePropertyChanged();
            }
        }

        private Person _Person;
        public Person Person
        {
            get
            {
                return _Person;
            }
            set
            {
                _Person = value;
                this.RaisePropertyChanged();
            }
        }
    }

    public class PersonListViewModel : NotificationObject
    {
        public PersonListViewModel()
        {
            _Persons.Add(new PersonModel() { Person = new Person() { ID = 1, Name = "张三" } });
            _Persons.Add(new PersonModel() { Person = new Person() { ID = 2, Name = "李四" } });
            _Persons.Add(new PersonModel() { Person = new Person() { ID = 3, Name = "王五" } });
            _Persons.Add(new PersonModel() { Person = new Person() { ID = 4, Name = "赵六" } });
            _Persons.Add(new PersonModel() { Person = new Person() { ID = 5, Name = "刘七" } });
            _Persons.Add(new PersonModel() { Person = new Person() { ID = 6, Name = "陈八" } });
        }

        private ObservableCollection<PersonModel> _Persons = new ObservableCollection<PersonModel>();
        public ObservableCollection<PersonModel> Persons
        {
            get
            {
                return _Persons;
            }
            set
            {
                _Persons = value;
                this.RaisePropertyChanged();
            }
        }


        private bool _IsSelectAll = false;
        public bool IsSelectAll
        {
            get { return _IsSelectAll; }
            set
            {
                _IsSelectAll = value;
                RaisePropertyChanged();
            }
        }


        private ICommand _SelectAllCommand;
        public ICommand SelectAllCommand
        {
            get
            {
                return _SelectAllCommand ?? (_SelectAllCommand = new DelegateCommand<object>(SelectAll));
            }
        }

        /// <summary>
        /// 全选
        /// </summary>
        /// <param name="id"></param>
        public void SelectAll(object id)
        {
            foreach (var item in Persons)
            {
                item.IsSelected = IsSelectAll;
            }
        }

        private ICommand _SelectCommand;
        public ICommand SelectCommand
        {
            get
            {
                return _SelectCommand ?? (_SelectCommand = new DelegateCommand<int>(Select));
            }
        }

        /// <summary>
        /// 单选
        /// </summary>
        /// <param name="id"></param>
        public void Select(int id)
        {
            PersonModel md = Persons.Where(p => p.Person.ID == id).FirstOrDefault();
            if (md != null)
            {
                if (!md.IsSelected && IsSelectAll)
                {
                    IsSelectAll = false;
                }
                else if (md.IsSelected && !IsSelectAll)
                {
                    foreach (var item in Persons)
                    {
                        if (!item.IsSelected) return;
                    }
                    IsSelectAll = true;
                }
            }
        }

        /// <summary>
        /// 判断是否选中
        /// </summary>
        /// <param name="onlyOne">是否单选</param>
        /// <returns></returns>
        public bool SelectValidate(bool onlyOne = false)
        {
            if (this.Persons.Count(p => p.IsSelected) < 1)
            {
                MessageBox.Show("未勾选数据!");
                return false;
            }

            if (onlyOne)
            {
                if (this.Persons.Count(p => p.IsSelected) > 1)
                {
                    MessageBox.Show("只能勾选一条数据!");
                    return false;
                }
            }

            return true;
        }

        private ICommand _DelCommand;
        public ICommand DelCommand
        {
            get
            {
                return _DelCommand ?? (_DelCommand = new DelegateCommand<object>(Del));
            }
        }

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="obj"></param>
        public void Del(object obj = null)
        {
            if (!SelectValidate()) return;

            MessageBoxResult result = MessageBox.Show("是否删除选中项?", "提示", MessageBoxButton.YesNo);
            if (result != MessageBoxResult.Yes)
            {
                return;
            }

            StringBuilder sb = new StringBuilder();

            bool hasSelect = false;
            //获取选中的数据
            foreach (var v in _Persons)
            {
                if (v.IsSelected) { sb.Append(v.Person.Name + ";"); hasSelect = true; }
            }
            if (!hasSelect)
            {
                MessageBox.Show("请选择修改项", "警告");
                return;
            }

            MessageBox.Show("选中 " + sb.ToString());
        }

        private ICommand _EditCommand;
        public ICommand EditCommand
        {
            get
            {
                return _EditCommand ?? (_EditCommand = new DelegateCommand<object>(Edit));
            }
        }

        /// <summary>
        /// 修改
        /// </summary>
        /// <param name="obj"></param>
        public void Edit(object obj = null)
        {
            if (!SelectValidate(true)) return;

            PersonModel model = null;


            bool hasSelect = false;
            //获取选中的数据
            foreach (var v in _Persons)
            {
                if (v.IsSelected) { model = v; hasSelect = true; break; }
            }
            if (!hasSelect)
            {
                MessageBox.Show("请选择修改项", "警告");
                return;
            }

            MessageBox.Show("选中 " + model.Person.Name);

        }
    }

3. View

<!--uc_PersonList.xaml-->
<!--需要将Checkbox的点击事件绑定到Command命令,引用System.Windows.Interactivity程序集可实现Event to Command功能,方式:引用 => 程序集 => 扩展 => System.Windows.Interactivity -->
<UserControl x:Class="MvvmDataGridCheckBoxSelectAll.uc_PersonList"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:MvvmDataGridCheckBoxSelectAll"
             xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
             mc:Ignorable="d">
    <UserControl.DataContext>
        <local:PersonListViewModel />
    </UserControl.DataContext>

    <DockPanel Margin="0">
        <StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
            <Button Command="{Binding EditCommand}" ToolTip="修改">
                <Button.Content>
                    <StackPanel Orientation="Horizontal" >
                        <Image Stretch="None" VerticalAlignment="Center" Source="../Images/List_Edit.png"/>
                        <TextBlock Text="修改" VerticalAlignment="Center"/>
                    </StackPanel>
                </Button.Content>
            </Button>
            <Button Command="{Binding DelCommand}" ToolTip="删除">
                <Button.Content>
                    <StackPanel Orientation="Horizontal" >
                        <Image Stretch="None" VerticalAlignment="Center" Source="../Images/List_Del.png"/>
                        <TextBlock Text="删除" VerticalAlignment="Center"/>
                    </StackPanel>
                </Button.Content>
            </Button>
            <!--<Button Command="{Binding RefreshCommand}" ToolTip="刷新">
                <Button.Content>
                    <StackPanel Orientation="Horizontal" >
                        <Image Stretch="None" VerticalAlignment="Center" Source="../Images/List_Refresh.png"/>
                        <TextBlock Text="刷新" VerticalAlignment="Center"/>
                    </StackPanel>
                </Button.Content>
            </Button>-->

        </StackPanel>

        <DataGrid x:Name="dataGrid" AutoGenerateColumns="False" GridLinesVisibility="None" CanUserAddRows="False" Focusable="False"   Margin="0" HorizontalAlignment="Left" VerticalAlignment="Top" ItemsSource="{Binding Persons}" Width="Auto" EnableColumnVirtualization="False">

            <DataGrid.ColumnHeaderStyle>
                <Style TargetType="DataGridColumnHeader">
                    <Setter Property="HorizontalContentAlignment" Value="Center">
                    </Setter>
                </Style>
            </DataGrid.ColumnHeaderStyle>
            <DataGrid.Columns>
                <DataGridTemplateColumn>
                    <DataGridTemplateColumn.Header>
                        <CheckBox IsChecked="{Binding DataContext.IsSelectAll,Mode=TwoWay, UpdateSourceTrigger=PropertyChanged,RelativeSource={RelativeSource AncestorType=UserControl, AncestorLevel=1 }}">
                            <i:Interaction.Triggers>
                                <i:EventTrigger EventName="Click">
                                    <i:InvokeCommandAction Command="{Binding DataContext.SelectAllCommand ,RelativeSource={RelativeSource AncestorType=UserControl, AncestorLevel=1 }}" ></i:InvokeCommandAction>
                                </i:EventTrigger>
                            </i:Interaction.Triggers>
                        </CheckBox>
                    </DataGridTemplateColumn.Header>
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <CheckBox Margin="3" IsChecked="{Binding IsSelected,Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
                                <i:Interaction.Triggers>
                                    <i:EventTrigger EventName="Click">
                                        <i:InvokeCommandAction Command="{Binding DataContext.SelectCommand ,RelativeSource={RelativeSource AncestorType=UserControl, AncestorLevel=1 }}" CommandParameter="{Binding Person.ID}" ></i:InvokeCommandAction>
                                    </i:EventTrigger>
                                </i:Interaction.Triggers>
                            </CheckBox>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>

                <DataGridTextColumn Binding="{Binding Person.Name}" Header="姓名" IsReadOnly="True" Width="*"></DataGridTextColumn>
            </DataGrid.Columns>
        </DataGrid>
    </DockPanel>
</UserControl>
  • 5
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 13
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值