王座视角 發表於 2025-7-29 12:04:00

Avalonia treedatagrid使用杂记

<p>这里只对最近使用到的分层树做一些记录,有复选框示例,支持父级选中状态改变子集同步变化</p>
<p>废话不多说,直接上源码</p>
<p>View布局</p>
<div class="cnblogs_code">
<pre>                &lt;<span style="color: rgba(0, 0, 0, 1)">TreeDataGrid
                  Height</span>=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">710</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
                  BorderBrush</span>=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Gray</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
                  CanUserResizeColumns</span>=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">False</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
                  FontSize</span>=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">16</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
                  Source</span>=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">{Binding TreeDataGridSource}</span><span style="color: rgba(128, 0, 0, 1)">"</span>&gt;
                  &lt;TreeDataGrid.Resources&gt;
                        &lt;DataTemplate x:Key=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">CheckBoxCellTemplate</span><span style="color: rgba(128, 0, 0, 1)">"</span> x:DataType=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">vm:TreeDataModel</span><span style="color: rgba(128, 0, 0, 1)">"</span>&gt;
                            &lt;CheckBox IsChecked=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">{Binding IsSelected, Mode=TwoWay}</span><span style="color: rgba(128, 0, 0, 1)">"</span> /&gt;
                        &lt;/DataTemplate&gt;
                  &lt;/TreeDataGrid.Resources&gt;
                &lt;/TreeDataGrid&gt;</pre>
</div>
<p>model对象</p>
<div class="cnblogs_code">
<pre>    <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> TreeDataModel : INotifyPropertyChanged
    {
      </span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)"> _name;

      </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)"> Name
      {
            </span><span style="color: rgba(0, 0, 255, 1)">get</span> { <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> _name; }
            </span><span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">
            {
                _name </span>=<span style="color: rgba(0, 0, 0, 1)"> value;
                OnPropertyChanged(nameof(Name));
            }
      }

      </span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">int</span>?<span style="color: rgba(0, 0, 0, 1)"> _age;


      </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">int</span>?<span style="color: rgba(0, 0, 0, 1)"> Age
      {
            </span><span style="color: rgba(0, 0, 255, 1)">get</span> { <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> _age; }
            </span><span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">
            {
                _age </span>=<span style="color: rgba(0, 0, 0, 1)"> value;
                OnPropertyChanged(nameof(Age));
            }
      }

      </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">bool</span><span style="color: rgba(0, 0, 0, 1)"> _isSelected;

      </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">bool</span><span style="color: rgba(0, 0, 0, 1)"> IsSelected
      {
            </span><span style="color: rgba(0, 0, 255, 1)">get</span> { <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> _isSelected; }
            </span><span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">
            {
                _isSelected </span>=<span style="color: rgba(0, 0, 0, 1)"> value;
                OnPropertyChanged(nameof(IsSelected));

                </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 如果是分类节点,更新所有子项的状态</span>
                <span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (IsCategory)
                {
                  </span><span style="color: rgba(0, 0, 255, 1)">foreach</span> (<span style="color: rgba(0, 0, 255, 1)">var</span> child <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> Children)
                  {
                        child.IsSelected </span>=<span style="color: rgba(0, 0, 0, 1)"> value;
                  }
                }
            }
      }

      </span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)"> _department;

      </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)"> Department
      {
            </span><span style="color: rgba(0, 0, 255, 1)">get</span> =&gt;<span style="color: rgba(0, 0, 0, 1)"> _department;
            </span><span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">
            {
                </span><span style="color: rgba(0, 0, 255, 1)">if</span> (_department !=<span style="color: rgba(0, 0, 0, 1)"> value)
                {
                  _department </span>=<span style="color: rgba(0, 0, 0, 1)"> value;
                  OnPropertyChanged(nameof(Department));
                }
            }
      }

      </span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)"> _category;

      </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">bool</span> IsCategory =&gt; !<span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">.IsNullOrEmpty(Category);

      </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">bool</span> IsExpanded { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span>; } = <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">;


      </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)"> Category
      {
            </span><span style="color: rgba(0, 0, 255, 1)">get</span> { <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> _category; }
            </span><span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">
            {
                _category </span>=<span style="color: rgba(0, 0, 0, 1)"> value;
                OnPropertyChanged(nameof(Category));
            }
      }


      </span><span style="color: rgba(0, 0, 255, 1)">private</span> ObservableCollection&lt;TreeDataModel&gt; _children = <span style="color: rgba(0, 0, 255, 1)">new</span> ObservableCollection&lt;TreeDataModel&gt;<span style="color: rgba(0, 0, 0, 1)">();

      </span><span style="color: rgba(0, 0, 255, 1)">public</span> ObservableCollection&lt;TreeDataModel&gt;<span style="color: rgba(0, 0, 0, 1)"> Children
      {
            </span><span style="color: rgba(0, 0, 255, 1)">get</span> { <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> _children; }
            </span><span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">
            {
                _children </span>=<span style="color: rgba(0, 0, 0, 1)"> value;
                OnPropertyChanged(nameof(Children));
            }
      }

      </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">event</span> PropertyChangedEventHandler?<span style="color: rgba(0, 0, 0, 1)"> PropertyChanged;

      </span><span style="color: rgba(0, 0, 255, 1)">protected</span> <span style="color: rgba(0, 0, 255, 1)">virtual</span> <span style="color: rgba(0, 0, 255, 1)">void</span> OnPropertyChanged( <span style="color: rgba(0, 0, 255, 1)">string</span>? propertyName = <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">)
      {
            PropertyChanged</span>?.Invoke(<span style="color: rgba(0, 0, 255, 1)">this</span>, <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> PropertyChangedEventArgs(propertyName));
      }

      </span><span style="color: rgba(0, 0, 255, 1)">protected</span> <span style="color: rgba(0, 0, 255, 1)">bool</span> SetField&lt;T&gt;(<span style="color: rgba(0, 0, 255, 1)">ref</span> T field, T value, <span style="color: rgba(0, 0, 255, 1)">string</span>? propertyName = <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">)
      {
            </span><span style="color: rgba(0, 0, 255, 1)">if</span> (EqualityComparer&lt;T&gt;.Default.Equals(field, value)) <span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">;
            field </span>=<span style="color: rgba(0, 0, 0, 1)"> value;
            OnPropertyChanged(propertyName);
            </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">;
      }
    }</span></pre>
</div>
<p>vm 数据刷新逻辑</p>
<div class="cnblogs_code">
<pre>    <span style="color: rgba(0, 0, 255, 1)">private</span> HierarchicalTreeDataGridSource&lt;TreeDataModel&gt; _treeDataGridSource =
      <span style="color: rgba(0, 0, 255, 1)">new</span> HierarchicalTreeDataGridSource&lt;TreeDataModel&gt;(<span style="color: rgba(0, 0, 255, 1)">new</span> List&lt;TreeDataModel&gt;<span style="color: rgba(0, 0, 0, 1)">());

    </span><span style="color: rgba(0, 0, 255, 1)">public</span> HierarchicalTreeDataGridSource&lt;TreeDataModel&gt;<span style="color: rgba(0, 0, 0, 1)"> TreeDataGridSource
    {
      </span><span style="color: rgba(0, 0, 255, 1)">get</span> { <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> _treeDataGridSource; }
      </span><span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">
      {
            _treeDataGridSource </span>=<span style="color: rgba(0, 0, 0, 1)"> value;
            OnPropertyChanged(nameof(TreeDataGridSource));
      }
    }

    </span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> TreeDataModel selectedItem;

    </span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> TreeDataModel SelectedItem
    {
      </span><span style="color: rgba(0, 0, 255, 1)">get</span> =&gt;<span style="color: rgba(0, 0, 0, 1)"> selectedItem;
      </span><span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">
      {
            selectedItem </span>=<span style="color: rgba(0, 0, 0, 1)"> value;
            OnPropertyChanged(nameof(SelectedItem));
      }
    }

    </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">async</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> InitTreeData()
    {
      List</span>&lt;TreeDataModel&gt; data = <span style="color: rgba(0, 0, 255, 1)">new</span> List&lt;TreeDataModel&gt;<span style="color: rgba(0, 0, 0, 1)">();
      </span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">int</span> i = <span style="color: rgba(128, 0, 128, 1)">0</span>; i &lt; <span style="color: rgba(128, 0, 128, 1)">10</span>; i++<span style="color: rgba(0, 0, 0, 1)">)
      {
            </span><span style="color: rgba(0, 0, 255, 1)">int</span> value = <span style="color: rgba(128, 0, 128, 1)">10</span> +<span style="color: rgba(0, 0, 0, 1)"> i;
            data.Add(</span><span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> TreeDataModel()
            {
                Age </span>=<span style="color: rgba(0, 0, 0, 1)"> value,
                Name </span>= $<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">示例{value}</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
                Department </span>= <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">测试部</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
            });
      }

      </span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">int</span> i = <span style="color: rgba(128, 0, 128, 1)">0</span>; i &lt; <span style="color: rgba(128, 0, 128, 1)">7</span>; i++<span style="color: rgba(0, 0, 0, 1)">)
      {
            </span><span style="color: rgba(0, 0, 255, 1)">int</span> value = <span style="color: rgba(128, 0, 128, 1)">10</span> +<span style="color: rgba(0, 0, 0, 1)"> i;
            data.Add(</span><span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> TreeDataModel()
            {
                Age </span>=<span style="color: rgba(0, 0, 0, 1)"> value,
                Name </span>= $<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">张三{value}</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
                Department </span>= <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">研发</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
            });
      }

      </span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(0, 0, 255, 1)">int</span> i = <span style="color: rgba(128, 0, 128, 1)">23</span>; i &lt; <span style="color: rgba(128, 0, 128, 1)">50</span>; i++<span style="color: rgba(0, 0, 0, 1)">)
      {
            </span><span style="color: rgba(0, 0, 255, 1)">int</span> value = <span style="color: rgba(128, 0, 128, 1)">10</span> +<span style="color: rgba(0, 0, 0, 1)"> i;
            data.Add(</span><span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> TreeDataModel()
            {
                Age </span>=<span style="color: rgba(0, 0, 0, 1)"> value,
                Name </span>= $<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">酒香也怕巷子深{value}</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
                Department </span>= <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">心如止水</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
            });
      }

      </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">聚合形成树形数据集</span>
      <span style="color: rgba(0, 0, 255, 1)">var</span> categoryGroups =<span style="color: rgba(0, 0, 0, 1)"> data
            .GroupBy(i </span>=&gt;<span style="color: rgba(0, 0, 0, 1)">
            {
                </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 按照"-"前面的部分分类</span>
                <span style="color: rgba(0, 0, 255, 1)">var</span> dashIndex = i.Department.IndexOf(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">-</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">);
                </span><span style="color: rgba(0, 0, 255, 1)">return</span> dashIndex &gt; <span style="color: rgba(128, 0, 128, 1)">0</span> ? i.Department.Substring(<span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">, dashIndex) : i.Department;
            });
      List</span>&lt;TreeDataModel&gt; listData = <span style="color: rgba(0, 0, 255, 1)">new</span> List&lt;TreeDataModel&gt;<span style="color: rgba(0, 0, 0, 1)">();
      </span><span style="color: rgba(0, 0, 255, 1)">foreach</span> (<span style="color: rgba(0, 0, 255, 1)">var</span> group <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> categoryGroups)
      {
            </span><span style="color: rgba(0, 0, 255, 1)">var</span> category = <span style="color: rgba(0, 0, 255, 1)">new</span> TreeDataModel { Category =<span style="color: rgba(0, 0, 0, 1)"> group.Key };

            </span><span style="color: rgba(0, 0, 255, 1)">foreach</span> (<span style="color: rgba(0, 0, 255, 1)">var</span> item <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> group)
            {
                category.Children.Add(item);
            }

            listData.Add(category);
      }

      TreeDataGridSource </span>=
            <span style="color: rgba(0, 0, 255, 1)">new</span> HierarchicalTreeDataGridSource&lt;TreeDataModel&gt;<span style="color: rgba(0, 0, 0, 1)">(listData)
            {
                Columns </span>=<span style="color: rgba(0, 0, 0, 1)">
                {
                  </span><span style="color: rgba(0, 0, 255, 1)">new</span> HierarchicalExpanderColumn&lt;TreeDataModel&gt;<span style="color: rgba(0, 0, 0, 1)">(
                        </span><span style="color: rgba(0, 0, 255, 1)">new</span> TextColumn&lt;TreeDataModel, <span style="color: rgba(0, 0, 255, 1)">string</span>&gt;<span style="color: rgba(0, 0, 0, 1)">(
                            </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">人员</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
                            x </span>=&gt; x.IsCategory ? $<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">{x.Category}({x.Children.Count}成员)</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)"> : x.Name,
                            GridLength.Auto)
                        ,
                        x </span>=&gt;<span style="color: rgba(0, 0, 0, 1)"> x.Children,
                        isExpandedSelector: x </span>=&gt;<span style="color: rgba(0, 0, 0, 1)"> x.IsExpanded),
                  </span><span style="color: rgba(0, 0, 255, 1)">new</span> TextColumn&lt;TreeDataModel, <span style="color: rgba(0, 0, 255, 1)">int</span>?&gt;<span style="color: rgba(0, 0, 0, 1)">(
                        </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">年龄</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
                        x </span>=&gt;<span style="color: rgba(0, 0, 0, 1)"> x.Age,
                        GridLength.Auto),
                  </span><span style="color: rgba(0, 0, 255, 1)">new</span> TemplateColumn&lt;TreeDataModel&gt;<span style="color: rgba(0, 0, 0, 1)">(
                        </span><span style="color: rgba(128, 0, 0, 1)">""</span><span style="color: rgba(0, 0, 0, 1)">,
                        </span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">CheckBoxCellTemplate</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 使用自定义模板</span>
<span style="color: rgba(0, 0, 0, 1)">                        width: GridLength.Auto),
                },
            };

      TreeDataGridSource.RowSelection.SelectionChanged </span>+= (s, e) =&gt;<span style="color: rgba(0, 0, 0, 1)">
      {
            </span><span style="color: rgba(0, 0, 255, 1)">if</span> (s <span style="color: rgba(0, 0, 255, 1)">is</span> TreeDataGridRowSelectionModel&lt;TreeDataModel&gt;<span style="color: rgba(0, 0, 0, 1)"> selec)
            {
                </span><span style="color: rgba(0, 0, 255, 1)">if</span> (selec.SelectedItem <span style="color: rgba(0, 0, 255, 1)">is</span><span style="color: rgba(0, 0, 0, 1)"> TreeDataModel selectModel)
                {
                  SelectedItem </span>=<span style="color: rgba(0, 0, 0, 1)"> selectModel;
                }
            }
      };
    }</span></pre>
</div>
<p>关键点,</p>
<p>1.数据格式绑定基本都在vm完成treedatagrid数据源集合需要绑定HierarchicalTreeDataGridSource,而不是传统的ObservableCollection</p>
<p>2.行选中时间SelectionChanged,控件不支持直接使用SelectionChanged,需要vm业务层订阅RowSelection来引出SelectionChanged,数据集每次变化都需要重新订阅</p>
<p>3.复选框:</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;数据集Columns绑定时其实有CheckBoxColumn列,不过这里演示通过绑定资源键的形式&nbsp;x:Key="CheckBoxCellTemplate"实现复选框</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; 父级状态改变影响子集,Avalonia原本的TreeDataGrid并没有对这个实现,但是自己可以通过通过对IsSelected属性变化时,验证IsCategory是否是分类节点 从而更改子集选中状态</p>
<p>&nbsp;</p><br><br>
来源:https://www.cnblogs.com/Zjl-NanKe/p/19010544
頁: [1]
查看完整版本: Avalonia treedatagrid使用杂记