You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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列:

  1. 修改ViewModel,公开性别列表
    在PersonViewModel中添加公开的性别列表属性,供XAML绑定下拉选项:

    public List<GenderModel> GenderList => _genderList;
    
  2. 给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>
    
  3. 实现事件处理逻辑
    在窗口后台代码中添加事件处理方法,判断属性类型并生成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);
        }
    }
    
  4. 修正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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 12:05:12