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

WPF中DataGridTemplateColumn内ComboBox绑定双属性类问题

问题:WPF DataGrid中绑定PropList类到ComboBox失败

我有一个绑定到DataTable的DataGrid,其中包含一列或多列类型为PropList的列。PropList类包含两个成员:string类型的CurrentValue和List<string>类型的Values。尝试将ComboBox的ItemsSource和SelectedValue绑定到这两个成员,但始终无法成功,已尝试多种方案无效。

相关代码片段

1. PropList类定义

public class PropList
{
    public string CurrentValue;
    public List<string> Values;

    public PropList(string val, List<string>list)
    {
        CurrentValue = val;
        Values = list;
    }
}

2. 创建DataTable列

clm = theTable.Columns.Add("The_Model_List", typeof(PropList));

3. DataGrid_AutoGeneratingColumn事件处理

if (e.PropertyType == typeof(PropList))
{
    var col = new PropListDataGridTemplateColumn
    {
        Header = e.PropertyName,
        ColumnName = e.PropertyName,
        CellTemplate = (DataTemplate)FindResource("PropListDataTemplate")
    };
    e.Column = col;
    return;
}

4. 自定义PropListDataGridTemplateColumn

//as found on stackoverflow
public class PropListDataGridTemplateColumn : DataGridTemplateColumn
{
    public string ColumnName
    {
        get;
        set;
    }
    protected override FrameworkElement GenerateElement(DataGridCell cell, object dataItem)
    {
        // The DataGridTemplateColumn uses ContentPresenter with your DataTemplate.
        var cp = base.GenerateElement(cell, dataItem);
        // Reset the Binding to the specific column. The default binding is to the DataRowView.
        cp.SetBinding(ContentPresenter.ContentProperty, new Binding(this.ColumnName));
        return cp;
    }
    protected override FrameworkElement GenerateEditingElement(DataGridCell cell, object dataItem)
    {
        // The DataGridTemplateColumn uses ContentPresenter with your DataTemplate.
        var cp = base.GenerateElement(cell, dataItem);
        // Reset the Binding to the specific column. The default binding is to the DataRowView.
        cp.SetBinding(ContentPresenter.ContentProperty, new Binding(this.ColumnName));
        return cp;
    }
}

5. XAML资源与DataGrid定义

<Window.Resources>
    <ResourceDictionary>
        <DataTemplate x:Key="PropListDataTemplate" DataType="DataRowView">
            <ComboBox HorizontalAlignment="Stretch" VerticalAlignment="Center" Margin="1" 
                          ItemsSource="{Binding Path=Values}" SelectedValue="{Binding Path=CurrentValue, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></ComboBox>
        </DataTemplate>
    </ResourceDictionary>
</Window.Resources>
<!-- other stuff -->
<DataGrid x:Name="PropData" Margin="5" ItemsSource="{Binding Path=EntityData, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" AlternatingRowBackground="AliceBlue" 
      SelectionUnit="Cell" SelectionMode="Extended"  CanUserAddRows="False" CanUserDeleteRows="False" CanUserReorderColumns="False" SelectedItem="{Binding SelectedEntity, UpdateSourceTrigger=PropertyChanged}"
      AutoGeneratingColumn="DataGrid_AutoGeneratingColumn" CellEditEnding="PropData_CellEditEnding"/>

补充说明:DataGrid的ItemsSource绑定到ViewModel中的DataTable(EntityData),PropList类对应的列已正确绑定,但无法将其两个成员绑定到ComboBox的ItemsSource和SelectedItem属性。

问题原因与解决方案

1. 将字段改为属性(核心问题)

WPF数据绑定仅支持绑定到属性,不支持绑定到字段。需将PropList中的字段改为带get/set访问器的属性:

public class PropList
{
    public string CurrentValue { get; set; }
    public List<string> Values { get; set; }

    public PropList(string val, List<string> list)
    {
        CurrentValue = val;
        Values = list;
    }
}

2. 修正DataTemplate的DataType

DataTemplate当前指定的DataType="DataRowView"不符合实际绑定对象(实际绑定的是PropList实例),需修改为:

<!-- 先在XAML头部添加命名空间,替换为你的PropList所在命名空间 -->
xmlns:local="clr-namespace:YourNamespace"

<DataTemplate x:Key="PropListDataTemplate" DataType="{x:Type local:PropList}">
    <ComboBox HorizontalAlignment="Stretch" VerticalAlignment="Center" Margin="1" 
              ItemsSource="{Binding Path=Values}" 
              SelectedValue="{Binding Path=CurrentValue, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</DataTemplate>

3. 修复自定义列的GenerateEditingElement方法

GenerateEditingElement方法中错误调用了base.GenerateElement,应改为base.GenerateEditingElement:

protected override FrameworkElement GenerateEditingElement(DataGridCell cell, object dataItem)
{
    var cp = base.GenerateEditingElement(cell, dataItem);
    cp.SetBinding(ContentPresenter.ContentProperty, new Binding(this.ColumnName));
    return cp;
}

4. 可选:实现INotifyPropertyChanged(支持动态更新)

如果需要在CurrentValue或Values变更时自动更新UI,PropList需实现INotifyPropertyChanged接口:

public class PropList : INotifyPropertyChanged
{
    private string _currentValue;
    public string CurrentValue
    {
        get => _currentValue;
        set
        {
            if (_currentValue != value)
            {
                _currentValue = value;
                OnPropertyChanged(nameof(CurrentValue));
            }
        }
    }

    private List<string> _values;
    public List<string> Values
    {
        get => _values;
        set
        {
            if (_values != value)
            {
                _values = value;
                OnPropertyChanged(nameof(Values));
            }
        }
    }

    public PropList(string val, List<string> list)
    {
        CurrentValue = val;
        Values = list;
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

内容的提问来源于stack exchange,提问作者Jeff Mishler

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 09:52:44