当项添加到基础ObservableCollection时,递归TreeView不保留结构

本文关键字:递归 TreeView 结构 保留 ObservableCollection 添加 | 更新日期: 2023-09-27 18:25:16

Am在此模型基础上构建递归WPF树视图:

public class Category
{
    public virtual ICollection<Category> Category1 { get; set; }
    public virtual Category Category2 { get; set; }
}

因此(名称不正确)类别1是子类别的集合,类别2是父类别。如果后者位于树的顶层,则它可以为null。

TreeView的呈现方式如下:

<TreeView ItemsSource="{Binding Categories}">
    <TreeView.ItemTemplate>
        <HierarchicalDataTemplate ItemsSource="{Binding Category1}">
            <Button Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.ViewContentsCommand}" 
                CommandParameter="{Binding}" Width="100" HorizontalAlignment="Stretch">
                <TextBlock FontWeight="Bold"  Text="{Binding Name}"></TextBlock>
            </Button>
        </HierarchicalDataTemplate>
    </TreeView.ItemTemplate>
</TreeView>

Categories是一个ObservableCollection,因此当用户通过UI添加或删除集合中的项目时,它应该会更新。在显示方面,这一切都如预期的那样。

我不明白的是,当用户向集合中添加项目时会发生什么。这是代码:

public void AddCategory()
{
    Category c = new Category { Description = "New Category",  Category2Id = SelectedCategory.CategoryId };
    Categories.Add(c);
    OnPropertyChanged("Categories"); //to refresh the UI
}

如果您在此处粘贴断点并检查Categories集合,则正如预期的那样——新项已插入到树中,位于其指定的ParentId之下。在顶层(即Category2Id为null的项目),项目数量与以前相同。但在UI中,这个新项目被渲染为处于顶层,而不是树中的正确位置。

起初,我想知道这是否是直接使用ObservableCollection的一个特点,所以我尝试了这个:

public void AddCategory()
{
    List<Category> cats = Categories.ToList();
    Category c = new Category { Description = "New Category",  Category2Id = SelectedCategory.CategoryId };
    cats.Add(c);
    Categories = cats.ToObservableCollection();
}

我本以为没有效果,但令我惊讶的是,这根本没有发生任何事情——也就是说,新类别根本没有出现在UI中。

我做错了什么?

当项添加到基础ObservableCollection时,递归TreeView不保留结构

在集合上调用Add方法不会提醒INotifyPropertyChanged接口任何更改。。。只需手动调用(接口方法的实现)。。。

NotifyPropertyChanged("Categories");

AddCategory方法的末尾,提醒接口注意Categories集合已更改的事实。