WPF入门教程系列二十九 ——DataGrid使用示例MVVM模式(7)

  • WPF入门教程系列二十九 ——DataGrid使用示例MVVM模式(7)已关闭评论
  • 119 次浏览
  • A+
所属分类:.NET技术
摘要

WPF入门教程系列五——Window 介绍     13.通过Command指令,传递了下拉框所选择的省份,datagrid自动显示相应省份的城市信息,但是以上示例中有一个Bug,就是下拉框中绑定的数据无法显示。

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

 
接上文WPF入门教程系列二十八 ——DataGrid使用示例MVVM模式(6)

    13.通过Command指令,传递了下拉框所选择的省份,datagrid自动显示相应省份的城市信息,但是以上示例中有一个Bug,就是下拉框中绑定的数据无法显示。

这是由于DataGridComboBoxColumn若要填充下拉列表,请先使用以下选项之一设置 ItemsSource 属性 ComboBox :

    1)静态资源。 使用StaticResource 标记扩展。

    2)x:Static 代码实体。 使用x:Static 标记扩展。

    3)类型的内联集合 ComboBoxItem 。

14.比较适合的绑定方式是  2)x:Static 代码实体。 使用x:Static 标记扩展需要添加相应的命名空间。在Visual Studio 2022中打开MainWindows.xmal文件,并在文件的开头添加如下命名空间。           

  xmlns:v="clr-namespace:WpfGridDemo.NET7.ViewModel"

15. 在Visual Studio 2022中打开MainWindows.xmal文件。对DataGridComboBoxColumn的ItemsSource进行了数据绑定。具体代码如下:

<DataGridComboBoxColumn Header="城市" Width="120"  x:Name="cboCity" 
ItemsSource
="{x:Static v:MainWindowVM.GridCityList}" ClipboardContentBinding="{x:Null}" SelectedValuePath="Code"
SelectedValueBinding
="{Binding Path=CityCode,UpdateSourceTrigger=PropertyChanged}"
DisplayMemberPath
="Name" SelectedItemBinding="{x:Null}" />

16.在Visual Studio 2022的解决方案资源管理器中,找到MainWindowVM.cs文件,将GridCityList属性改为静态属性,用于绑定DataGridComboBoxColumn的ItemsSource。具体如下代码:
        private static ObservableCollection<City> cityList;         public static ObservableCollection<City> GridCityList         {              get { return cityList; }             set             {                  cityList = value;                 new ViewModelBase().RaisePropertyChanged("GridCityList");             }          }

17.在Visual Studio 2022中按F5键,启动WPF应用程序。然后使用鼠标点击省份下拉框,能够看到,界面中DataGrid中的数据,随着下拉框的变化而随之变化,但是城市下拉框中却没有任何数据。看来绑定失效了。如下图。

 WPF入门教程系列二十九 ——DataGrid使用示例MVVM模式(7)

 

 

 

 

18. 使用静态代码实体的方式,实现省市县联动失败了。又不想使用其他两种方式。在一阵猛于虎的搜索之后,发现一种实现方式。在Visual Studio 2022中打开MainWindows.xmal文件。对DataGridComboBoxColumn进行了数据绑定。具体代码如下:

<DataGridComboBoxColumn Header="城市(Style)" SelectedValuePath="Code"
SelectedValueBinding="{Binding Path=CityCode,UpdateSourceTrigger=PropertyChanged}"
DisplayMemberPath
="Name" SelectedItemBinding="{x:Null}" Width="1*"> <DataGridComboBoxColumn.EditingElementStyle> <Style TargetType="ComboBox"> <Setter Property="ItemsSource"
Value
="{Binding Path=DataContext.GridCity,ElementName=gridArea}" /> </Style> </DataGridComboBoxColumn.EditingElementStyle> <DataGridComboBoxColumn.ElementStyle> <Style TargetType="ComboBox"> <Setter Property="ItemsSource"
Value
="{Binding Path=DataContext.GridCity,ElementName=gridArea}" /> </Style> </DataGridComboBoxColumn.ElementStyle> </DataGridComboBoxColumn>

              

19.在Visual Studio 2022的解决方案资源管理器中,找到MainWindowVM.cs文件,添加一个GridCity属性,用于绑定DataGridComboBoxColumn的ItemsSource。以下是属性代码,更完整的代码,请参见下面类的完整代码。

private ObservableCollection<City> listCity;          public ObservableCollection<City> GridCity         {              get { return listCity; }             set             {                 listCity = value;                 RaisePropertyChanged("GridCity");             }         }

20.MainWindow.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"           xmlns:v="clr-namespace:WpfGridDemo.NET7.ViewModel"         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" x:Name="cboCity"
ItemsSource
="{x:Static v:MainWindowVM.GridCityList}" ClipboardContentBinding="{x:Null}" SelectedValuePath="Code"
SelectedValueBinding
="{Binding Path=CityCode,UpdateSourceTrigger=PropertyChanged}"
DisplayMemberPath
="Name" SelectedItemBinding="{x:Null}" /> <DataGridComboBoxColumn Header="城市(Style)" SelectedValuePath="Code"
SelectedValueBinding="{Binding Path=CityCode,UpdateSourceTrigger=PropertyChanged}"
DisplayMemberPath
="Name" SelectedItemBinding="{x:Null}" Width="1*"> <DataGridComboBoxColumn.EditingElementStyle> <Style TargetType="ComboBox"> <Setter Property="ItemsSource"
Value
="{Binding Path=DataContext.GridCity,ElementName=gridArea}" /> </Style> </DataGridComboBoxColumn.EditingElementStyle> <DataGridComboBoxColumn.ElementStyle> <Style TargetType="ComboBox"> <Setter Property="ItemsSource"
Value
="{Binding Path=DataContext.GridCity,ElementName=gridArea}" /> </Style> </DataGridComboBoxColumn.ElementStyle> </DataGridComboBoxColumn> <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>

 

21. MainWindowsVM类的完整代码,如下:
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>();              listCity = new ObservableCollection<City>();             }          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 static ObservableCollection<City> cityList;          public static ObservableCollection<City> GridCityList         {              get { return cityList; }              set             {                 cityList = value;                 new ViewModelBase().RaisePropertyChanged("GridCityList");             }         }           private ObservableCollection<City> listCity;          public ObservableCollection<City> GridCity          {             get { return listCity; }             set              {                 listCity = value;                 RaisePropertyChanged("GridCity");             }          }          /// <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); } ); } listCity.Clear(); if (citys != null) { citys.ForEach((t) => { listCity.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); } } } }

22.在Visual Studio 2022中按F5键,启动WPF应用程序。然后使用鼠标点击省份下拉框,能够看到,界面中DataGrid中的数据,随着下拉框的变化而随之变化,其中使用静态实体代码绑定的城市下拉框中却没有任何数据。使用使用非静态资源,在<DataGridComboBoxColumn.EditingElementStyle>与 <DataGridComboBoxColumn.ElementStyle>两个样式中绑定combobox的itemSource属性方式,效果有效。如下图。

WPF入门教程系列二十九 ——DataGrid使用示例MVVM模式(7)