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

Revit API中WPF TreeView父级勾选批量选中子级的实现问题

解决Revit API可停靠面板中WPF TreeView父级复选框全选子级问题

核心方案

  • 保留原有Dictionary<string, List<ViewProperties>>数据结构,通过包装ViewModel适配WPF绑定
  • 给父级分组、子级视图分别加IsChecked属性,父级勾选时循环设置所有子级状态(规避递归,适配Revit环境)
  • 分离TreeViewItem.IsSelected和CheckBox.IsChecked,实现选择查看与勾选操作独立

具体实现步骤

1. 扩展数据模型

给原ViewProperties类添加IsChecked属性并实现INotifyPropertyChanged(如果原类没实现的话):

public class ViewProperties : INotifyPropertyChanged
{
    // 你的原有属性(比如视图名称、ID等)
    public string ViewName { get; set; }

    private bool _isChecked;
    public bool IsChecked
    {
        get => _isChecked;
        set
        {
            if (_isChecked != value)
            {
                _isChecked = value;
                OnPropertyChanged(nameof(IsChecked));
            }
        }
    }

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

创建分组ViewModel,包装字典的键值对并处理父级勾选逻辑:

public class ViewGroupViewModel : INotifyPropertyChanged
{
    public string GroupName { get; set; }
    public List<ViewProperties> Views { get; set; }

    private bool _isChecked;
    public bool IsChecked
    {
        get => _isChecked;
        set
        {
            if (_isChecked != value)
            {
                _isChecked = value;
                // 用循环替代递归,设置所有子项的勾选状态
                foreach (var view in Views)
                {
                    view.IsChecked = value;
                }
                OnPropertyChanged(nameof(IsChecked));
            }
        }
    }

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

2. 转换字典为可绑定集合

在Page的后台代码或ViewModel中,把原字典转成ObservableCollection<ViewGroupViewModel>用于TreeView绑定,同时保留原字典引用:

// 保留原有字典数据
private Dictionary<string, List<ViewProperties>> _originalViewDict;
// 给TreeView绑定的集合
public ObservableCollection<ViewGroupViewModel> GroupedViewData { get; set; }

// 初始化TreeView数据
private void LoadTreeData()
{
    _originalViewDict = GetProcessedViewData(); // 替换成你获取字典数据的方法
    GroupedViewData = new ObservableCollection<ViewGroupViewModel>();
    
    foreach (var kvp in _originalViewDict)
    {
        GroupedViewData.Add(new ViewGroupViewModel
        {
            GroupName = kvp.Key,
            Views = kvp.Value
        });
    }

    // 设置页面DataContext,确保XAML能绑定到属性
    this.DataContext = this;
}

3. XAML配置TreeView

用HierarchicalDataTemplate分别定义父级分组和子级视图的模板,明确分离复选框与选中状态:

<TreeView ItemsSource="{Binding GroupedViewData}">
    <TreeView.Resources>
        <!-- 子级视图项模板 -->
        <HierarchicalDataTemplate x:Key="ViewItemTemplate" DataType="{x:Type local:ViewProperties}">
            <StackPanel Orientation="Horizontal">
                <CheckBox IsChecked="{Binding IsChecked}" Margin="0,0,6,0"/>
                <TextBlock Text="{Binding ViewName}" /> <!-- 替换成你要显示的视图属性 -->
            </StackPanel>
        </HierarchicalDataTemplate>
        <!-- 父级分组项模板 -->
        <HierarchicalDataTemplate DataType="{x:Type local:ViewGroupViewModel}"
                                  ItemsSource="{Binding Views}"
                                  ItemTemplate="{StaticResource ViewItemTemplate}">
            <StackPanel Orientation="Horizontal">
                <CheckBox IsChecked="{Binding IsChecked}" Margin="0,0,6,0"/>
                <TextBlock Text="{Binding GroupName}" FontWeight="SemiBold"/>
            </StackPanel>
        </HierarchicalDataTemplate>
    </TreeView.Resources>
</TreeView>

4. 注意事项

  • 所有绑定属性必须实现INotifyPropertyChanged,否则UI不会同步更新
  • 用循环替代递归处理子级勾选,避免Revit环境下的兼容性问题
  • TreeView的选中状态(IsSelected)由WPF默认管理,和复选框的IsChecked完全独立,天然满足“选择查看图片不勾选”的需求

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 02:52:49