WPF中用Behavior绑定DataGrid的SelectedItems失效,BindingExpression始终为Null
WPF DataGrid SelectedItems双向绑定Behavior问题
我试图通过Behavior实现WPF DataGrid的SelectedItems双向绑定,创建了DataGridSelectItemsBehavior类,定义了MySlectItemsProperty依赖属性,监听SelectionChanged事件以更新绑定值。但在事件处理方法中,调用dataGrid.GetBindingExpression(MySlectItemsProperty)得到的结果始终为null。ViewModel中已经定义了UserSelectedItems1和Select属性,Visual Studio也未提示任何绑定失败信息,无法定位问题。
行为类代码
public class DataGridSelectItemsBehavior : Behavior<DataGrid> { public static readonly DependencyProperty MySlectItemsProperty = DependencyProperty.Register("MySlectItems", typeof(IList), typeof(DataGridSelectItemsBehavior), new PropertyMetadata(null)); public static readonly DependencyProperty SelectIndexProperty = DependencyProperty.Register("SelectIndex", typeof(int), typeof(DataGridSelectItemsBehavior), new PropertyMetadata(-1)); public IList MySlectItems { get { return (IList)GetValue(MySlectItemsProperty); } set { SetValue(MySlectItemsProperty, value); } } public int SelectIndex { get { return (int)GetValue(SelectIndexProperty); } set { SetValue(SelectIndexProperty, value); } } protected override void OnAttached() { base.OnAttached(); AssociatedObject.SelectionChanged += AssociatedObject_SelectionChanged; } private void AssociatedObject_SelectionChanged(object sender, SelectionChangedEventArgs e) { var dataGrid = sender as DataGrid; if (dataGrid != null) { MySlectItems = dataGrid.SelectedItems; SelectIndex = dataGrid.SelectedIndex; var s = dataGrid.GetBindingExpression(MySlectItemsProperty); } } protected override void OnDetaching() { base.OnDetaching(); AssociatedObject.SelectionChanged -= AssociatedObject_SelectionChanged; } }
XAML代码
<DataGrid x:Name="datagrid1" xmlns:diagnostics="clr-namespace:System.Diagnostics;assembly=System" VerticalContentAlignment="Center" AutoGenerateColumns="False" CanUserAddRows="False" CanUserDeleteRows="False" ItemsSource="{Binding personInfos}"> <i:Interaction.Behaviors> <local:DataGridSelectItemsBehavior MySlectItems="{Binding UserSelectedItems1, Mode=TwoWay}" SelectIndex="{Binding Select, Mode=TwoWay}" /> </i:Interaction.Behaviors> <DataGrid.Columns> <DataGridTextColumn Binding="{Binding Index}" Header="序号" /> <DataGridTextColumn Binding="{Binding Age}" Header="年龄" /> <DataGridTextColumn Binding="{Binding Salary}" Header="工资" /> <DataGridTextColumn Binding="{Binding Phone}" Header="电话" /> <DataGridTextColumn Binding="{Binding Address}" Header="住址" /> </DataGrid.Columns> </DataGrid>
问题解决方法
1. 修正绑定表达式获取对象
MySlectItemsProperty是DataGridSelectItemsBehavior的依赖属性,不属于DataGrid。你错误地从DataGrid实例获取绑定表达式,应该从Behavior自身获取:
var s = this.GetBindingExpression(MySlectItemsProperty);
2. 修复双向绑定的集合同步逻辑
直接赋值MySlectItems = dataGrid.SelectedItems会导致引用替换,而DataGrid的SelectedItems是只读集合,无法被ViewModel修改同步。需要改为手动同步集合内容,同时处理ViewModel到DataGrid的反向同步:
- 修改依赖属性定义,添加双向绑定默认设置和属性变更回调:
public static readonly DependencyProperty MySlectItemsProperty = DependencyProperty.Register( "MySlectItems", typeof(IList), typeof(DataGridSelectItemsBehavior), new FrameworkPropertyMetadata( null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnMySelectItemsChanged)); private static void OnMySelectItemsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var behavior = d as DataGridSelectItemsBehavior; var dataGrid = behavior?.AssociatedObject; if (dataGrid == null || e.NewValue == null) return; // 临时取消事件监听,避免循环触发 dataGrid.SelectionChanged -= behavior.AssociatedObject_SelectionChanged; try { dataGrid.SelectedItems.Clear(); foreach (var item in (IList)e.NewValue) { dataGrid.SelectedItems.Add(item); } } finally { dataGrid.SelectionChanged += behavior.AssociatedObject_SelectionChanged; } }
- 更新
SelectionChanged事件处理方法,同步集合内容而非替换引用:
private void AssociatedObject_SelectionChanged(object sender, SelectionChangedEventArgs e) { var dataGrid = sender as DataGrid; if (dataGrid == null || MySlectItems == null) return; dataGrid.SelectionChanged -= AssociatedObject_SelectionChanged; try { MySlectItems.Clear(); foreach (var item in dataGrid.SelectedItems) { MySlectItems.Add(item); } SelectIndex = dataGrid.SelectedIndex; // 手动更新绑定源(可选,若绑定未自动触发) this.GetBindingExpression(MySlectItemsProperty)?.UpdateSource(); } finally { dataGrid.SelectionChanged += AssociatedObject_SelectionChanged; } }
3. 确保ViewModel集合可修改
ViewModel中的UserSelectedItems1必须是可修改的集合类型,比如ObservableCollection<T>,而非只读集合,否则无法同步选中项内容。
内容的提问来源于stack exchange,提问作者Mr li
相关产品推荐
相关产品推荐

