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

Revit 2021.1:DataGridRow选中时IsSelected属性不始终为True

问题解决:DataGrid行选中状态与ViewModel属性绑定不同步

问题描述

开发Revit 2021.1插件时,使用WPF DataGrid将行的IsSelected属性绑定到ElementParameterWrapper类的IsObjectSelected属性,但出现异常:即使DataGrid行已显示选中状态,IsObjectSelected有时仍为False。怀疑该问题与同时在两个DataGrid中选择对象有关。

涉及代码

XAML中的DataGrid及RowStyle

<DataGrid Grid.Row="1"
          Grid.Column="0"
          HorizontalAlignment="Left"
          Margin="10,0,10,10"
          ItemsSource="{Binding ListOfElementParameterWrappers, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
          RowStyle="{StaticResource RowToBeSelectedStyle}"
          AutoGenerateColumns="False"
          VerticalScrollBarVisibility="Auto"
          HorizontalScrollBarVisibility="Hidden"
          CanUserAddRows="False"
          CanUserResizeColumns="False"
          CanUserSortColumns="False"
          IsReadOnly="False"
          SelectionMode="Single"
          SelectionUnit="FullRow">
</DataGrid>

<Window.Resources>
    <Style x:Key="RowToBeSelectedStyle" TargetType="{x:Type DataGridRow}">
        <Setter Property="IsSelected" Value="{Binding IsObjectSelected}"/>
    </Style>
</Window.Resources>

ElementParameterWrapper类代码

public ElementParameterWrapper(Parameter parameter)
{
    Name = parameter.Definition.Name;
    Id = parameter.Id;
    if (parameter.IsShared)
    {
        GUID = parameter.GUID;
    }
}
public string Name { get; set; }
public ElementId Id { get; set; }
public Guid GUID { get; set; }
private bool isObjectSelected;
public bool IsObjectSelected
{
    get { return isObjectSelected; }
    set { isObjectSelected = value; }
}

解决方案

1. 明确绑定的双向模式与更新时机

默认绑定可能未启用双向同步,或更新触发时机滞后。修改RowStyle中的绑定配置:

<Style x:Key="RowToBeSelectedStyle" TargetType="{x:Type DataGridRow}">
    <Setter Property="IsSelected" Value="{Binding IsObjectSelected, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</Style>

2. 实现INotifyPropertyChanged接口

ElementParameterWrapper未实现属性变更通知,会导致UI与ViewModel状态同步中断。修改类代码:

public class ElementParameterWrapper : INotifyPropertyChanged
{
    public ElementParameterWrapper(Parameter parameter)
    {
        Name = parameter.Definition.Name;
        Id = parameter.Id;
        if (parameter.IsShared)
        {
            GUID = parameter.GUID;
        }
    }

    public string Name { get; set; }
    public ElementId Id { get; set; }
    public Guid GUID { get; set; }

    private bool isObjectSelected;
    public bool IsObjectSelected
    {
        get { return isObjectSelected; }
        set 
        { 
            if (isObjectSelected != value)
            {
                isObjectSelected = value;
                OnPropertyChanged(nameof(IsObjectSelected));
            }
        }
    }

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

3. 解决多DataGrid选择冲突

若两个DataGrid共享关联数据源,易出现选中状态互相覆盖:

  • 确保两个DataGrid的SelectionMode和SelectionUnit配置一致;
  • 避免两个DataGrid绑定的集合存在重复对象引用;
  • 在ViewModel中为每个DataGrid单独维护选中项属性,替代依赖对象自身的IsObjectSelected:
    // ViewModel中新增两个选中项属性
    private ElementParameterWrapper _selectedItemGrid1;
    public ElementParameterWrapper SelectedItemGrid1
    {
        get => _selectedItemGrid1;
        set 
        {
            _selectedItemGrid1 = value;
            OnPropertyChanged(nameof(SelectedItemGrid1));
            // 可选:同步更新对象选中状态
            if (_selectedItemGrid1 != null)
                _selectedItemGrid1.IsObjectSelected = true;
        }
    }
    
    private ElementParameterWrapper _selectedItemGrid2;
    public ElementParameterWrapper SelectedItemGrid2
    {
        get => _selectedItemGrid2;
        set 
        {
            _selectedItemGrid2 = value;
            OnPropertyChanged(nameof(SelectedItemGrid2));
            if (_selectedItemGrid2 != null)
                _selectedItemGrid2.IsObjectSelected = true;
        }
    }
    
    对应XAML中给每个DataGrid绑定SelectedItem:
    <!-- 第一个DataGrid -->
    <DataGrid ... SelectedItem="{Binding SelectedItemGrid1, Mode=TwoWay}" />
    
    <!-- 第二个DataGrid -->
    <DataGrid ... SelectedItem="{Binding SelectedItemGrid2, Mode=TwoWay}" />
    

4. 处理Revit线程调度问题

Revit API要求操作必须在主线程执行,若绑定涉及Revit对象,需确保数据更新在正确线程:

// 使用Dispatcher确保在UI线程更新属性
Application.Current.Dispatcher.Invoke(() =>
{
    // 更新ViewModel属性或集合的操作
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 10:51:31