通过 ICommand 更新后 WPF TreeView 结构丢失

问题描述 投票:0回答:1

我正在开发一个 WPF 项目,目前它实现了

ComboBox
Button
ICommand
TreeView
TreeView
是通过绑定到
ICommand
Button
接口生成的。运行应用程序时,从
ComboBox
选择项目并单击
Button
后,我的 TreeView 将按预期显示。 xaml:

<Window.Resources>
        <vm:RevitVM x:Key="viewmodel"/>
        <HierarchicalDataTemplate DataType="{x:Type vm:ParentNew}"
                                  ItemsSource="{Binding Children}">
            <TextBlock Text="{Binding Name}"/>
        </HierarchicalDataTemplate>
        <DataTemplate DataType="{x:Type vm:ChildNew}">
            <TextBlock Text="{Binding Name}"/>
        </DataTemplate>
        
    </Window.Resources>

    <Grid DataContext="{StaticResource viewmodel}">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="2*"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="6*"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <StackPanel Grid.Row="1">
            <ComboBox ItemsSource="{Binding UniqueAreaTypes}"
                      SelectedItem="{Binding SelectedAreaType}">
                <ComboBox.ItemTemplate>
                    <DataTemplate>
                        <StackPanel>
                            <TextBlock Text="{Binding AreaType}"/>
                        </StackPanel>
                    </DataTemplate>
                </ComboBox.ItemTemplate>
            </ComboBox>
        </StackPanel>
        <Button Content="Search" 
            Command="{Binding SearchCommand}"
            Grid.Row="5"
            Grid.Column="0"
            Margin="4"/>
        <TreeView
            Grid.Row="1"
            Grid.Column="1">
            <TreeViewItem ItemsSource="{Binding FamilyList}" Header="Test"
                         IsExpanded="False"/>
        </TreeView>
    </Grid>

当展开 TreeView 然后第二次使用

Button
时(无论
ComboBox
所选项目如何),就会出现问题。我的
TreeView 
仅显示更新的父项,而不显示
Children
。看起来绑定不知何故丢失了。

        public RevitVM()
        {
            SearchCommand = new SearchCommand(this);
            FamilyList = new ObservableCollection<ParentNew>();
        }



        public void SetTree()
        {
            FamilyList.Clear();
            foreach (var a in AreasToShow)
            {
                ParentNew parent = new ParentNew(); 
                parent.Name = a.Name;
                FamilyList.Add(parent); 
                ObservableCollection<ChildNew> children = new ObservableCollection<ChildNew>();
                foreach (var r in RoomsToShow)
                {
                    if (r.Position == a.Position) 
                    {
                        ChildNew child = new ChildNew();
                        child.Name = r.Name;
                        children.Add(child);
                    }
                }
                parent.Children = children;
            }
        }


        public void MakeQuery()
        {
            SetTree();
        }

这是否与我通过

ObservableCollection<ParentNew> FamilyList
接口清除并重写属性
ICommand
有关?

public class SearchCommand : ICommand
{
    public RevitVM VM { get; set; }

    public SearchCommand(RevitVM revitVM)
    {
        VM = revitVM;
    }

    public event EventHandler? CanExecuteChanged;

    public bool CanExecute(object? parameter)
    {
        return true;
    }

    public void Execute(object? parameter)
    {
        VM.MakeQuery();
    }

ParentNew
班:

public class ParentNew
{
    public string Name { get; set; }
    public int Id { get; set; }
    public ObservableCollection<ChildNew> Children { get; set; }
}

我期待更新的

FamilyList
属性显示在窗口上,同时在展开树并单击
Button
后保持其结构。

值得注意的是,如果

TreeViewItem.IsExpanded
设置为
False
not 手动展开并单击
Button
,则
TreeView
会保持其结构并更新后的
Children
。 当我在 xaml 中将
TreeViewItem.IsExpanded
设置为
True
时,即使我是第一次运行该应用程序,TreeView 也不会显示
Children
TreeViewItem.IsExpanded
是否触发了我看不到的东西?

目前我没有使用任何后台代码,而且我也不打算这样做。我对 C# 语言和 WPF 也相当陌生,因此我尝试通过阅读有关该主题的几篇 StackOverflow 帖子来寻找答案,但没有成功。我缺少什么?预先感谢。

c# wpf data-binding treeview
1个回答
0
投票

您分配了 Children 集合 (

parent.Children = children;
),但 UI 现在不支持这一点。

为了确保 UI 更新,请在 ParentNew 类中实现 INotifyPropertyChange 接口并引发 PropertyChange 事件。

但还有一个简单的修复方法 - 在将父对象添加到 FamilyList 之前分配集合:

ObservableCollection<ChildNew> children = new ObservableCollection<ChildNew>();
parent.Children = children;
FamilyList.Add(parent); 

foreach (var r in RoomsToShow)
{
    if (r.Position == a.Position) 
    {
        ChildNew child = new ChildNew();
        child.Name = r.Name;
        children.Add(child);
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.