WPF入门教程系列二十八 ——DataGrid使用示例MVVM模式

Posted DotNet菜园

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了WPF入门教程系列二十八 ——DataGrid使用示例MVVM模式相关的知识,希望对你有一定的参考价值。

在WPF开发中,经典的编程模式是MVVM,该模式充分利用了WPF的数据绑定机制,最大限度地降低了Xmal文件和CS文件的耦合度,也就是UI显示和逻辑代码的耦合度,如需要更换界面时,逻辑代码修改很少,甚至不用修改。 MVVM是Model、View、ViewModel的简写,MVVM的根本思想就是界面和业务功能进行分离,View的职责就是负责如何显示数据及发送命令,ViewModel的功能就是如何提供数据和执行命令。各司其职,互不影响。 理想情况下界面和逻辑是完全分离的,单方面更改界面时不需要对逻辑代码改动,同样的逻辑代码更改时也不需要更改界面。同一个ViewModel可以使用完全不用的View进行展示,同一个View也可以使用不同的ViewModel以提供不同的操作。

WPF入门教程系列五——Window 介绍

 
 
 

八、在Command中传递参数

7.上面Buttom的Command类就是纯命令,什么参数都不接收,这次的ProvinceChangedCommand类在执行命令的时候,能够传参数!采用泛型的形式,给Action添加泛型参数。

8. 在Visual Studio 2022的解决方案资源管理器中,使用鼠标右键单击“Command”文件夹,在弹出菜单中选择“添加--> 类”,在弹出的“添加新项”对话框中,选择添加 “ProvinceChangedCommand”类,这是一个我们要实现的保存操作指令,然后选择“添加”。ProvinceChangedCommand的具体代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Threading.Tasks;
using System.Windows.Input;
 
namespace WpfGridDemo.NET7.Command

    public class ProvinceChangedCommand<T> : ICommand
    
        /// <summary>
        /// 命令能否执行
        /// </summary>
        readonly Func<bool> _canExecute;
        /// <summary>
        /// 命令执行的方法
        /// </summary>
        readonly Action<T> _execute;
 
        /// <summary>
        /// 命令的构造函数
        /// </summary>
        /// <param name="action">命令需执行的方法</param>
        /// <param name="canExecute">命令是否可以执行的方法</param>
        public ProvinceChangedCommand(Action<T> action, Func<bool> canExecute)
        
            _execute = action;
            _canExecute = canExecute;
        
 
        /// <summary>
        /// 判断命令是否可以执行
        /// </summary>
        /// <param name="parameter"></param>
        /// <returns></returns>
        public bool CanExecute(Object parameter)
        
            if (_canExecute == null)
                return true;
            return _canExecute();
        
 
        /// <summary>
        /// 执行命令
        /// </summary>
        /// <param name="parameter"></param>
        public void Execute(Object parameter)
        
            _execute((T)parameter);
        
 
        /// <summary>
        /// 事件追加、移除
        /// </summary>
        public event EventHandler CanExecuteChanged
        
            add
            
                if (_canExecute != null)
                    CommandManager.RequerySuggested += value;
            
            remove
            
                if (_canExecute != null)
                    CommandManager.RequerySuggested -= value;
            
        
 
    

void ProviceSelectionChangedExecute(object sender)
        
            try
            
                if (sender is ComboBox)
                
                    ComboBox drp=sender as ComboBox;
                    ProvinceCode=drp.SelectedValue.ToString();
                    GridDbContext db = new GridDbContext();
                    var list = db.City.AsTracking().ToList();
                    List<City> citys = list.Where(x => x.ProvinceCode == ProvinceCode).ToList();
                    cityList = new ObservableCollection<City>();
                    if (citys != null)
                    
                        citys.ForEach((t) =>
 
                         cityList.Add(t); 
                        );
                    
 
                    var cityCodes = from city in citys
                                    select city.Code;
                    List<Area> areas = db.Area.AsTracking().ToList().Where(
x => cityCodes.Contains(x.CityCode)).ToList(); areaList = new ObservableCollection<Area>(); if (areas!=null) areas.ForEach((t) => areaList.Add(t); ); catch (Exception ex) throw ex;

结果如图:我们看到了省份下拉框中已经了省份信息。

 

9.通过绑定依赖属性,实现自动刷新需要实现以下三步:

1.Model继承并实现 INotifyPropertyChanged 接口;

2.数据集合使用ObservableCollection<T>集合;

3.View使用Binding数据对象属性;

如果不行再看看集合在赋值前需要实例化,不然就出不来(必须要同一个源才行)

10. 在Visual Studio 2022中打开MainWindows.xmal文件,并将文件中的代码修改成如下:

<Window x:Class="WpfGridDemo.NET7.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:be="http://schemas.microsoft.com/xaml/behaviors"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfGridDemo.NET7"
        mc:Ignorable="d"
        Title="MainWindow" Height="600" Width="960" Loaded="Window_Loaded" >
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="100"></RowDefinition>
            <RowDefinition Height="*"></RowDefinition>
            <RowDefinition Height="25"></RowDefinition>
        </Grid.RowDefinitions>
        <WrapPanel Grid.Row="0" HorizontalAlignment="Left">
            <ComboBox x:Name="cboProvince" DisplayMemberPath="Name" SelectedValuePath="Code" >
 
                <be:Interaction.Triggers>

                    <be:EventTrigger EventName="SelectionChanged">
                        <be:InvokeCommandAction Command="Binding ProviceChangedAction" 
CommandParameter
="Binding ElementName=cboProvince"/> </be:EventTrigger> </be:Interaction.Triggers> </ComboBox> </WrapPanel> <DataGrid x:Name="gridArea" Grid.Row="1" ItemsSource="Binding GridAreaList"
AutoGenerateColumns
="False" HorizontalAlignment="Left" VerticalAlignment="Top"
SelectedItem
="Binding Path=AreaVM, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged"> <DataGrid.Columns> <DataGridComboBoxColumn Header="城市" Width="120"
ItemsSource
="Binding Path=DataContext.GridCityList,
RelativeSource=RelativeSource AncestorType=x:Type Window
"
x:Name
="cboCity" ClipboardContentBinding="x:Null"
SelectedValuePath="Code" SelectedValueBinding="Binding Path=CityCode,
UpdateSourceTrigger=PropertyChanged
"
DisplayMemberPath
="Name" SelectedItemBinding="x:Null" /> <DataGridTextColumn Header="县区镇" Width="*" Binding="Binding Name"
ClipboardContentBinding
="x:Null"/> <DataGridTextColumn Header="邮编" Width="100" Binding="Binding Code"
ClipboardContentBinding
="x:Null"/> <DataGridTextColumn Header="创建时间" Width="160" Binding="Binding Created"
ClipboardContentBinding
="x:Null"/> <DataGridTextColumn Header="更新时间" Width="160" Binding="Binding Updated"
ClipboardContentBinding
="x:Null"/> </DataGrid.Columns> </DataGrid> <WrapPanel Grid.Row="2"> <Button x:Name="btnRefresh" Height="22" Width="120" Click="btnRefresh_Click">刷新</Button> <Button x:Name="btnSave" Height="22" Width="120" Command="Binding ClickSaveAction" >保存</Button> </WrapPanel> </Grid> </Window>

 

11. 在Visual Studio 2022中打开MainWindowsVM.cs文件,实现下拉框的选择事件的Command命令绑定,将通过Command参数传递过来的省份信息,用于数据查询,同时通知UI界面进行数据刷新。具体如下代码:
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.DirectoryServices.ActiveDirectory;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Windows.Input;
using WpfGridDemo.NET7.Entitys;
 
namespace WpfGridDemo.NET7.ViewModel

    public class MainWindowVM: ViewModelBase
    
        public MainWindowVM() 
            cityList = new ObservableCollection<City>();
            areaList = new ObservableCollection<Area>();
        
        private Area m_Area;
        /// <summary>
        /// 县镇区数据
        /// </summary>
        public Area AreaVM
        
            get  return m_Area; 
            set  m_Area = value; 
        
        private string m_Province_Code;
        /// <summary>
        /// 省--代码
        /// </summary>
        public string ProvinceCode  get => m_Province_Code; set => m_Province_Code = value; 
        private ObservableCollection<Area> areaList;
 
         public ObservableCollection<Area> GridAreaList
         
             get  return areaList; 
             set
             
                areaList = value;
                 RaisePropertyChanged("GridAreaList");
             
        
        private ObservableCollection<City> cityList;
 
        public ObservableCollection<City> GridCityList
        
            get  return cityList; 
            set
            
                cityList = value;
                RaisePropertyChanged("GridCityList");
            
        
    
        /// <summary>
        /// 命令要执行的方法
        /// </summary>
        void SaveExecute()
        
            try
 
            
                GridDbContext db = new GridDbContext();
                var list=db.Area.AsTracking().ToList();
                Area modifyArea = list.Where(x=>x.Id==AreaVM.Id).FirstOrDefault();
                if (modifyArea != null)
                
                    modifyArea.Name = AreaVM.Name;
                    modifyArea.Updated = DateTime.Now;
                    db.SaveChanges();
                
 
            
            catch (Exception ex)
            
 
                throw ex;
            
        
 
        /// <summary>
        /// 命令是否可以执行
        /// </summary>
        /// <returns></returns>
        bool CanSaveExecute()
        
            return false;
        
 
        /// <summary>
        /// 创建新命令
        /// </summary>
        public ICommand ClickSaveAction
        
            get
            
                return new Command.SaveCommand(SaveExecute, CanSaveExecute);
            
        
        //combobox
        /// <summary>
        /// 命令要执行的方法
        /// </summary>
        void ProviceSelectionChangedExecute(object sender)
        
            try
 
            
                if (sender is ComboBox)
                
                    ComboBox drp=sender as ComboBox;
                    ProvinceCode=drp.SelectedValue.ToString();
                    GridDbContext db = new GridDbContext();
                    var list = db.City.AsTracking().ToList();

                    List<City> citys = list.Where(x => x.ProvinceCode == ProvinceCode).ToList();
                    var cityCodes = from city in citys
                                    select city.Code;
                    List<Area> areas = db.Area.AsTracking().ToList().Where(
x => cityCodes.Contains(x.CityCode)).ToList(); areaList.Clear(); if (areas!=null) areas.ForEach((t) => areaList.Add(t); ); cityList.Clear(); if (citys != null) citys.ForEach((t) => cityList.Add(t); ); catch (Exception ex) throw ex; /// <summary> /// 命令是否可以执行 /// </summary> /// <returns></returns> bool CanSelectionChangedExecute() return true; /// <summary> /// 创建新命令 /// </summary> public ICommand ProviceChangedAction get return new Command.ProvinceChangedCommand<object>(ProviceSelectionChangedExecute, CanSelectionChangedExecute);

12.在Visual Studio 2022中按F5键,启动WPF应用程序。然后使用鼠标点击省份下拉框,能够看到,界面中DataGrid中的数据,随着下拉框的变化而随之变化。如下图。

 

以上是关于WPF入门教程系列二十八 ——DataGrid使用示例MVVM模式的主要内容,如果未能解决你的问题,请参考以下文章

WPF入门教程系列十八——WPF中的数据绑定

WPF入门教程系列二十——ListView示例

ROS从入门到精通系列(二十八)-- ROS控制器图形化界面开发

WPF学习第二十八章 程序集资源

《C#零基础入门之百识百例》(二十八)交错数组 -- foreach求和

Python从入门到精通五万六千字对Python基础知识做一个了结吧!(二十八)值得收藏