利用DataGrid控件实现联动的功能,在数据库客户软件中是随处可见的,然而网上的资料却是少之又少,令人崩溃。
本篇博文将介绍利用DataGrid控件模板定义的三个ComboBox实现“省、市、区”的三级联动。步骤如下:
class RegionInfo : INotifyPropertyChanged //地区信息 { private string _province;//省 private string _city;//市 private string _area;//区 public event PropertyChangedEventHandler PropertyChanged; public string Province { get { return _province; } set { _province = value; PropertyChanged(this, new PropertyChangedEventArgs("Province")); } } public string City { get { return _city; } set { _city = value; PropertyChanged(this, new PropertyChangedEventArgs("City")); } } public string Area { get { return _area; } set { _area = value; PropertyChanged(this, new PropertyChangedEventArgs("Area")); } } public RegionInfo(string province, string city, string area)//构造函数 { _province = province; _city = city; _area = area; } }
<!--AutoGenerateColumns="False"这句话告诉控件不自动生成列,是必要的,如果没有,控件会更具数据源自动生成列,这个在我们这种写法中看起来就有重复的两列数据--> <DataGrid x:Name="dataGrid" ItemsSource="{Binding}" AutoGenerateColumns="False" HorizontalAlignment="Left" VerticalAlignment="Top" Height="319" Width="302"> <DataGrid.Columns> <!--省--> <DataGridTemplateColumn Header="省" Width="100"> <!--显示模式--> <DataGridTemplateColumn.CellTemplate> <DataTemplate> <TextBlock Text="{Binding Path=Province ,Mode=TwoWay}"></TextBlock> </DataTemplate> </DataGridTemplateColumn.CellTemplate> <!--编辑模式--> <DataGridTemplateColumn.CellEditingTemplate> <DataTemplate> <ComboBox x:Name="ComboBoxProvince" DropDownClosed="ProvinceDropDownClosed" Loaded="ProvinceLoaded" Text="{Binding Path=Province ,Mode=TwoWay}" DisplayMemberPath="Province" ></ComboBox> </DataTemplate> </DataGridTemplateColumn.CellEditingTemplate> </DataGridTemplateColumn> <!--市--> <DataGridTemplateColumn Header="市" Width="100"> <!--显示模式--> <DataGridTemplateColumn.CellTemplate> <DataTemplate> <TextBlock Text="{Binding Path=City ,Mode=TwoWay}"></TextBlock> </DataTemplate> </DataGridTemplateColumn.CellTemplate> <!--编辑模式--> <DataGridTemplateColumn.CellEditingTemplate> <DataTemplate> <ComboBox x:Name="ComboBoxCity" DropDownClosed="CityDropDownClosed" Loaded="CityLoaded" Text="{Binding Path=City,Mode=TwoWay}" DisplayMemberPath="City" ></ComboBox> </DataTemplate> </DataGridTemplateColumn.CellEditingTemplate> </DataGridTemplateColumn> <!--区--> <DataGridTemplateColumn Header="区" Width="100"> <!--显示模式--> <DataGridTemplateColumn.CellTemplate> <DataTemplate> <TextBlock Text="{Binding Path=Area}"></TextBlock> </DataTemplate> </DataGridTemplateColumn.CellTemplate> <!--编辑模式--> <DataGridTemplateColumn.CellEditingTemplate> <DataTemplate> <ComboBox x:Name="ComboBoxArea" DropDownClosed="AreaDropDownClosed" Loaded="AreaLoaded" Text="{Binding Path=Area}" DisplayMemberPath="Area" ></ComboBox> </DataTemplate> </DataGridTemplateColumn.CellEditingTemplate> </DataGridTemplateColumn> </DataGrid.Columns> </DataGrid>
对象声明
ObservableCollection<RegionInfo> regionInfoList = new ObservableCollection<RegionInfo>();//DataGrid的数据源对象添加
//DataGrid初始绑定数据 regionInfoList.Add(new RegionInfo("广东省", "深圳市", "罗湖区")); regionInfoList.Add(new RegionInfo("广东省", "深圳市", "南山区"));对象绑定
dataGrid.ItemsSource = regionInfoList;//绑定数据源
对象声明
ObservableCollection<RegionInfo> regionInfoSelectList = new ObservableCollection<RegionInfo>();//用于DataGrid的模板列加载时提供选项对象添加
//三级联动数据项 regionInfoSelectList.Add(new RegionInfo("广东省", "深圳市", "罗湖区")); regionInfoSelectList.Add(new RegionInfo("广东省", "深圳市", "南山区")); regionInfoSelectList.Add(new RegionInfo("广东省", "潮州市", "湘桥区")); regionInfoSelectList.Add(new RegionInfo("广东省", "潮州市", "枫溪区")); regionInfoSelectList.Add(new RegionInfo("湖北省", "武汉市", "江夏区")); regionInfoSelectList.Add(new RegionInfo("湖北省", "武汉市", "武昌区"));
/// <summary> /// ProvinceLoaded 省份下拉列表框初始化,绑定数据源 /// </summary> void ProvinceLoaded(object sender, RoutedEventArgs e) { ComboBox curComboBox = sender as ComboBox; //为下拉控件绑定数据源,并选择原选项为默认选项 string text = curComboBox.Text; //去除重复项查找,跟数据库连接时可以让数据库来实现 var query = regionInfoSelectList.GroupBy(p => p.Province).Select(p => new { Province = p.FirstOrDefault().Province }); int itemcount = 0; curComboBox.SelectedIndex = itemcount; foreach (var item in query.ToList()) { if (item.Province == text) { curComboBox.SelectedIndex = itemcount; break; } itemcount++; } curComboBox.ItemsSource = query; curComboBox.IsDropDownOpen = true;//获得焦点后下拉 } /// <summary> /// CityLoaded 市下拉列表框初始化,绑定数据源 /// </summary> void CityLoaded(object sender, RoutedEventArgs e) { //获得当前选中项的省份信息 string province = (dataGrid.SelectedItem as RegionInfo).Province; //查找选中省份下的市作为数据源 var query = (from l in regionInfoSelectList where (l.Province == province) group l by l.City into grouped select new { City = grouped.Key }); ComboBox curComboBox = sender as ComboBox; //为下拉控件绑定数据源,并选择原选项为默认选项 string text = curComboBox.Text; //去除重复项查找,跟数据库连接时可以让数据库来实现 int itemcount = 0; curComboBox.SelectedIndex = itemcount; foreach (var item in query.ToList()) { if (item.City == text) { curComboBox.SelectedIndex = itemcount; break; } itemcount++; } curComboBox.ItemsSource = query; curComboBox.IsDropDownOpen = true;//获得焦点后下拉 } /// <summary> /// AreaLoaded 区下拉列表框初始化,绑定数据源 /// </summary> void AreaLoaded(object sender, RoutedEventArgs e) { string province = (dataGrid.SelectedItem as RegionInfo).Province; string city = (dataGrid.SelectedItem as RegionInfo).City; //查找选中省份下的市作为数据源 var query = (from l in regionInfoSelectList where (l.Province == province && l.City == city) group l by l.Area into grouped select new { Area = grouped.Key }); ComboBox curComboBox = sender as ComboBox; //为下拉控件绑定数据源,并选择原选项为默认选项 string text = curComboBox.Text; //去除重复项查找,跟数据库连接时可以让数据库来实现 int itemcount = 0; curComboBox.SelectedIndex = itemcount; foreach (var item in query.ToList()) { if (item.Area == text) { curComboBox.SelectedIndex = itemcount; break; } itemcount++; } curComboBox.ItemsSource = query; curComboBox.IsDropDownOpen = true;//获得焦点后下拉 }
做到这一步基本上算是做完了,但是编译运行后会发现在选择省或者市的时候,后面的选项并没有做相应的改变,这是上一篇文章 C# WPF DataGrid控件同行编辑的实时更新问题 所述的问题,所以还需最后一步
哦哦,更新代码分别写在
/// <summary> /// CityDropDownClosed 市下拉列表框选择改变刷新 /// </summary> private void CityDropDownClosed(object sender, EventArgs e) { } /// <summary> /// ProvinceDropDownClosed 省份下拉列表框选择改变刷新 /// </summary> private void ProvinceDropDownClosed(object sender, EventArgs e) { } /// <summary> /// AreaDropDownClosed 区下拉列表框选择改变刷新 /// </summary> private void AreaDropDownClosed(object sender, EventArgs e) { }
这三个函数中。如果还想再只能点,在省下拉列表选择后,市下拉列表下拉。市下拉列表选择后,区下拉列表下拉,则可以参考 C# WPF 模拟键盘输入与UI控件进行交互 这篇文章,然后在上面提到的省、市两个下拉列表框中模拟键盘按下“TAD”键即可。
DEMO工程