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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 06:54:51