WPF DataGrid不同行绑定不同列表的实现问询
实现WPF DataGrid行级动态切换ComboBox数据源的方案
核心思路
DataGridComboBoxColumn的ItemsSource是全局绑定的,无法实现行级动态切换。解决办法是改用DataGridTemplateColumn嵌入ComboBox,通过每行数据对象的属性动态返回对应数据源,同时实现属性变更通知让UI自动更新。
步骤1:修改ProfileItem类
让类实现INotifyPropertyChanged接口,添加一个根据IsRound动态返回数据源的属性,并在IsRound变化时通知UI更新:
using System.ComponentModel; using System.Runtime.CompilerServices; internal class ProfileItem : INotifyPropertyChanged { public string ProfileName { get; set; } private bool _isRound; public bool IsRound { get => _isRound; set { if (_isRound != value) { _isRound = value; OnPropertyChanged(); OnPropertyChanged(nameof(AvailableProfileTypes)); // 切换时触发数据源更新 } } } public string ProfileType { get; set; } public Element ProfileElement { get; set; } // 全局共享的类型列表(也可通过构造函数传入,根据项目结构调整) public static List<string> RoundProfileTypeNames { get; set; } public static List<string> RectProfileTypeNames { get; set; } // 动态返回当前行对应的数据源 public IEnumerable<string> AvailableProfileTypes { get => IsRound ? RoundProfileTypeNames : RectProfileTypeNames; } public event PropertyChangedEventHandler PropertyChanged; private void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }
步骤2:修改XAML布局
替换原DataGridComboBoxColumn为DataGridTemplateColumn,让每行的ComboBox绑定到AvailableProfileTypes:
<DataGrid Name="profilePropsGrid" Width="500" CanUserReorderColumns="False" HorizontalAlignment="Center" CanUserAddRows="False" VerticalAlignment="Top" AutoGenerateColumns="False"> <DataGrid.Columns> <DataGridTextColumn Header="Profile Name" Width="*" Binding="{Binding ProfileName}" IsReadOnly="true" /> <DataGridTemplateColumn Header="Is Rounded Profile?" Width="*"> <DataGridTemplateColumn.CellTemplate> <DataTemplate> <CheckBox IsChecked="{Binding IsRound, Mode=TwoWay}" /> </DataTemplate> </DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn> <DataGridTemplateColumn Width="100" Header="Profile Type"> <DataGridTemplateColumn.CellTemplate> <DataTemplate> <ComboBox ItemsSource="{Binding AvailableProfileTypes}" SelectedItem="{Binding ProfileType, Mode=TwoWay}" DisplayMemberPath="." /> </DataTemplate> </DataGridTemplateColumn.CellTemplate> <!-- 编辑模式模板(与显示模板一致即可) --> <DataGridTemplateColumn.CellEditingTemplate> <DataTemplate> <ComboBox ItemsSource="{Binding AvailableProfileTypes}" SelectedItem="{Binding ProfileType, Mode=TwoWay}" DisplayMemberPath="." /> </DataTemplate> </DataGridTemplateColumn.CellEditingTemplate> </DataGridTemplateColumn> </DataGrid.Columns> </DataGrid>
步骤3:调整后台代码
将全局类型列表传递给ProfileItem,并简化IsRound的赋值逻辑:
// 先初始化全局类型列表(假设你已经完成这一步) // roundProfileTypeNames = new List<string> { ... }; // rectProfileTypeNames = new List<string> { ... }; // 传递给ProfileItem的静态属性 ProfileItem.RoundProfileTypeNames = roundProfileTypeNames; ProfileItem.RectProfileTypeNames = rectProfileTypeNames; bridgeProfileList = new List<ProfileItem>(); foreach (Element elem in framingPipeTypesCol) { ProfileItem ep = new ProfileItem() { ProfileName = elem.Name, ProfileElement = elem }; IList<Parameter> pipe_shape_circle = elem.GetParameters("Pipe Shape_Circle"); if (pipe_shape_circle.Count > 0) { ep.IsRound = pipe_shape_circle[0].AsInteger() == 1; } bridgeProfileList.Add(ep); } profilePropsGrid.ItemsSource = bridgeProfileList; // 移除原有的ProfileType.ItemsSource赋值,现在由每行自己管理数据源
关键说明
- 放弃
DataGridComboBoxColumn:该列的ItemsSource是全局配置,无法实现行级动态切换,改用模板列可以绑定到每行数据对象的属性。 - 属性变更通知:
INotifyPropertyChanged确保当IsRound勾选状态变化时,AvailableProfileTypes的变更能及时通知UI,自动切换ComboBox的数据源。 - 移除事件处理:原
CheckBox的Checked/Unchecked事件不再需要,TwoWay绑定会自动同步IsRound的值,触发后续的数据源更新。
内容的提问来源于stack exchange,提问作者Amir
相关产品推荐
相关产品推荐

