利用DataGrid控件实现联动的功能,在数据库客户软件中是随处可见的,然而网上的资料却是少之又少,令人崩溃。
本篇博文将介绍利用DataGrid控件模板定义的三个ComboBox实现“省、市、区”的三级联动。步骤如下:
一.定义地域信息类(注意包含System.ComponentModel命名空间)
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;
}
}
二.编写DataGrid控件的XAML代码
<!--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>
三.为DataGrid控件准备数据源对象
对象声明
ObservableCollection<RegionInfo> regionInfoList = new ObservableCollection<RegionInfo>();//DataGrid的数据源
对象添加
//DataGrid初始绑定数据
regionInfoList.Add(new RegionInfo("广东省", "深圳市", "罗湖区"));
regionInfoList.Add(new RegionInfo("广东省", "深圳市", "南山区"));
对象绑定
dataGrid.ItemsSource = regionInfoList;//绑定数据源
四.为DataGrid控件的模板列加载时提供选项
对象声明
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("湖北省", "武汉市", "武昌区"));
五.在DataGrid模板列加载的时候实时更新其数据源并绑定到ComboBox的选项中
/// <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控件同行编辑的实时更新问题 所述的问题,所以还需最后一步
六.参考 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”键即可。