如何在ItemsSource更改时刷新树视图?

时间:2011-11-10 21:28:10

标签: wpf mvvm treeview refresh

My TreeView绑定到ObservableCollection并使用HierarchicalDataTemplates。

我从网络服务中获取模型。

仅当用户单击树中的节点时,才会发送Web服务调用以获取其子项。

我的应用程序有一个TabControl,TreeView在一个标签页上,另一个标签页有一个数据网格,它有一些从树视图中选择的数据。右键单击datagrid中的项目时,我想在treeview上找到该项目。但现在问题是当我迭代树视图时, 说,我有一个名为

的项目
  

A.A1.A11

我的TreeView在第一级有3个项目:

一个

C

当我找到 A.A1.A11 时,我想展开 A,A1和突出显示 A11。

当我迭代树视图时,首先我找到A,它匹配A.A1.A11的第一条路径, 所以我发送了一个网络服务请求,以便让A的孩子们。

一旦我得到它,A的TreeViewItem的DataContext被更新,但TreeViewItem本身不是。

因此,当我检查A.Items时,它是空的并且迭代无法继续。

如何刷新TreeVuew& TreeViewItem在其ItemsSource更改时?

这是树视图定义的xaml

<TreeView x:Name="TreeRoot" 
          ItemsSource="{Binding RootItems}" 
          TreeViewItem.Expanded="TreeViewExpanded"
          TreeView.SelectedItemChanged="TreeRootSelectedItemChanged"
          ContextMenu="{StaticResource DataGridContextMenu}"
          PreviewKeyDown="TreeViewKeyDown"
          PreviewMouseLeftButtonDown="TreeViewPreviewLeftMouseButtonDown"
          PreviewMouseMove="TreeViewPreviewMouseMove" >
    <TreeView.Resources>
        <HierarchicalDataTemplate 
            DataType="{x:Type m:TreeModelBase}" 
            ItemsSource="{Binding Children}">    
            <StackPanel>
                <Image Source="{Binding ImageFilePath}" />
                <TextBlock Text="{Binding Name}" />
                <!-- other items removed for brevity -->
                <StackPanel.Style>
                <Style TargetType="{x:Type StackPanel}">
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding IsSelected}"
                                     Value="True">  
                        <Setter Property="Background" Value="DodgerBlue"/>
                        <Setter Property="TextBlock.Foreground" 
                                Value="White"/>
                        </DataTrigger>
                        <DataTrigger Binding="{Binding IsSelected}"
                                     Value="False">  
                        <Setter Property="Background" Value="White"/>
                        <Setter Property="TextBlock.Foreground" 
                                Value="Black"/>
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </StackPanel.Style>
            </StackPanel>
        </HierarchicalDataTemplate>
    </TreeView.Resources>
</TreeView>

4 个答案:

答案 0 :(得分:3)

RootItems是否实现了更改INotifyProperty并且您是否正在调用NotifyPropertyChanged?集合需要是一个ObservableCollection(而不是List),以便UI了解更新。

答案 1 :(得分:0)

填充TreeViewItem的子项时,不更新DataContext,更新ItemsSource。因此,在服务获取A的子代之后,您需要将结果List(或ObservableCollection)分配给A.ItemsSource。

答案 2 :(得分:0)

我找到了&amp;设法让它工作。但它根本不是最佳选择。我做了什么,首先迭代viewModel,发送Web服务请求以获取A的孩子,然后发送另一个请求来获取A1的孩子。这是第一关。其次,从根搜索树视图并在迭代时生成ItemContainers。首先,搜索树的根,获取节点A(treeviewItem),然后应用模板,从ItemContainerGenerator获取容器(参见详细信息@ {3}}),然后我就能在树视图中找到该项并展开其路径。任何人都知道更好的方式,让我知道。谢谢

答案 3 :(得分:0)

如果您正在使用DataContext和正确的数据绑定技术,可以通过将PropertyChanged连接到每个项目并导出TreeViewItem来实现TreeViewItem的更新,如下所述(重置DataContext和模板)树项目)。 此示例仅刷新第二级项目(第二个条件),当然可能很容易扩展。

在我的例子中,ElementItem是ObservableList中每个项目的基类,并实现了INotifyProperty。

    ...

    itemInObservableList.PropertyChanged += Ep_PropertyChanged;

    ...

    private void Ep_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
    {
            var twi = this.pageList.ItemContainerGenerator.ContainerFromItem(
                (sender as ElementItem).Parent ) as TreeViewItem;
            if (twi != null)
            {
                var twii = twi.ItemContainerGenerator.ContainerFromItem(sender) as TreeViewItem;
                if (twii != null)
                {
                 //second level items refresh   
                    var dc = twii.DataContext;
                    var tpl = twii.Template;
                    twii.DataContext = null;
                    twii.Template = null;
                    twii.DataContext = sender ;
                    twii.Template = tpl;
                    twii.UpdateLayout();
                }  
            }
    }