WPF实现DataGrid自动生成关联数据的ComboBox列
如何让WPF DataGrid自动为关联数据生成可选择的ComboBox列?
我的应用中存在带关联表的数据源,例如产品表仅存储产品类型ID、人员表存储性别类型ID。我希望通过通用DataGrid自动生成列来展示不同表的数据,简单类型(如String、int)已正常显示,但关联数据无法自动生成可选择的ComboBox列。
以下是我尝试的代码:
XAML代码
<Grid> <DataGrid x:Name="T_DataGrid" AutoGenerateColumns="True" EnableRowVirtualization="True" ItemsSource="{Binding DataCollection}" Margin="10,10,10,8" RowDetailsVisibilityMode="VisibleWhenSelected" Grid.Row="1"> </DataGrid> </Grid>
PersonModel
public class PersonModel { public PersonModel(int genderType) { _GenderType = genderType; } public int Age { get; set; } public String Name { get; set; } private static int _GenderType { get; set; } public GenderModel GenderType { get; set; } }
GenderModel
public class GenderModel { public GenderModel() { } public int Type { get; set; } public string Description { get; set; } public override string ToString() { return $"{Type} -> {Description}"; } }
PersonViewModel(窗口DataContext)
public PersonViewModel() { _genderList.Add(new GenderModel { Type = 1, Description = "Male" }); _genderList.Add(new GenderModel { Type = 2, Description = "FeMale" }); _genderList.Add(new GenderModel { Type = 3, Description = "What Ever You Want For My Own Peace" }); DataCollection.Add(new PersonModel(1) { Age = 20, Name = "Peter" }); DataCollection.Add(new PersonModel(2) { Age = 22, Name = "Lydia" }); DataCollection.Add(new PersonModel(3) { Age = 30, Name = "It is not your business because i'm not female or male" }); foreach (var person in _dataCollection) { person.GenderType = _genderList.FirstOrDefault(); } } private ObservableCollection<PersonModel> _dataCollection = new ObservableCollection<PersonModel>(); public ObservableCollection<PersonModel> DataCollection { get { return _dataCollection; } set => SetProperty(ref _dataCollection, value); } private List<GenderModel> _genderList = new List<GenderModel>();
实现方案
WPF DataGrid默认自动生成列时,只会为简单值类型生成常规列,不会自动识别关联对象并生成ComboBox列。要实现这个需求,需要通过AutoGeneratingColumn事件拦截列生成过程,手动替换为ComboBox列:
修改ViewModel,公开性别列表
在PersonViewModel中添加公开的性别列表属性,供XAML绑定下拉选项:public List<GenderModel> GenderList => _genderList;给DataGrid添加AutoGeneratingColumn事件
修改XAML中的DataGrid,添加事件绑定:<DataGrid x:Name="T_DataGrid" AutoGenerateColumns="True" EnableRowVirtualization="True" ItemsSource="{Binding DataCollection}" Margin="10,10,10,8" RowDetailsVisibilityMode="VisibleWhenSelected" Grid.Row="1" AutoGeneratingColumn="T_DataGrid_AutoGeneratingColumn"> </DataGrid>实现事件处理逻辑
在窗口后台代码中添加事件处理方法,判断属性类型并生成ComboBox列:private void T_DataGrid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e) { // 拦截GenderModel类型的列生成 if (e.PropertyType == typeof(GenderModel)) { // 取消默认生成的列 e.Cancel = true; // 创建ComboBox列 var comboBoxColumn = new DataGridComboBoxColumn { Header = e.Column.Header, // 绑定当前行数据的GenderType属性 SelectedItemBinding = new Binding(e.PropertyName), // 绑定下拉选项到ViewModel的GenderList ItemsSource = ((PersonViewModel)DataContext).GenderList, // 设置下拉列表显示的字段 DisplayMemberPath = "Description" }; // 将自定义列添加到DataGrid ((DataGrid)sender).Columns.Add(comboBoxColumn); } }修正Model中的问题
原PersonModel中的_GenderType是静态字段,会导致所有实例共享同一个值,改为实例字段:public class PersonModel { private int _genderType; // 去掉static,改为实例字段 public PersonModel(int genderType) { _genderType = genderType; } public int Age { get; set; } public string Name { get; set; } public GenderModel GenderType { get; set; } }同时修正ViewModel中给Person赋值GenderType的逻辑,根据构造时传入的ID匹配对应的性别:
foreach (var person in _dataCollection) { // 先给PersonModel添加公开的GenderTypeId属性 // public int GenderTypeId { get; } // 再匹配对应性别 person.GenderType = _genderList.FirstOrDefault(g => g.Type == person.GenderTypeId); }
内容的提问来源于stack exchange,提问作者brobro
相关产品推荐
相关产品推荐

