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

6vl6ewon  于 2023-10-22  发布在  其他
关注(0)|答案(1)|浏览(100)

我正在开发一个WPF项目,目前实现了ComboBoxButtonICommandTreeViewTreeView通过绑定到ButtonICommand接口生成。在运行应用程序时,从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();
        }

这是否与我通过ICommand接口清除并重写属性ObservableCollection<ParentNew> FamilyList有关?

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; }
}

我希望在展开树并单击Button后,更新后的FamilyList属性会显示在Window上,同时保持其结构。
值得注意的是,如果TreeViewItem.IsExpanded被设置为False手动展开并单击Button,则TreeView将保持其结构,并更新Children。当我在xaml中将TreeViewItem.IsExpanded设置为True时,即使我第一次运行应用程序,TreeView也不会显示ChildrenTreeViewItem.IsExpanded是否触发了我无法看到的内容?
目前我没有使用任何代码背后,我不打算。我对C#语言和WPF也是相当陌生的,所以我试图通过阅读几篇关于这个主题的StackOverflow文章来寻找答案,但无济于事。我错过了什么?先谢了。

nr9pn0ug

nr9pn0ug1#

你分配了Children集合(parent.Children = children;),但是UI不知道。
要确保UI已更新,请在ParentNew类中实现INotifyPropertyChanged接口并引发PropertyChanged事件。
但是在将父对象添加到FamilyList之前,还有一个简单的fix - assign集合:

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);
    }
}

相关问题