是否可以在 DataContext 更改时保存 TreeView 的状态(扩展节点,SelectedItem)。
DataContext 的结构在更改时不会更改。
<TreeView ItemsSource="{Binding Fields}">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type vm:NodeVM}" ItemsSource="{Binding Childs}" >
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}" MinWidth="80"/>
<TextBlock Text="{Binding Value}"/>
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
虚拟机:
public class NodeVM : BaseVM
{
public string Name { get; set; }
public string Value
{
get { return _value; }
set { _value = value; RaisePropertyChanged(); }
}
public List<NodeVM> Childs { get; set; }
public NodeVM()
{
Childs = new List<NodeVM>();
}
string _value;
}
public List<NodeVM> Fields { get; set; }
根据评论中的建议,我替换了更改的节点,但子节点的状态并没有以这种方式保存。

问题已经解决了——更新时,作者收到了一个列表,在此基础上作者构建了一棵树并完整显示,自然不会保存这种情况下的状态。这里有两种方法 - 单独保存状态并将其覆盖在新树中,或者不重新创建对象,而是更改现有对象。这两种选择都不理想。我将为第二个提供解决方案。
这两个选项都需要区分元素,例如,通过 Id,所以我将添加这样一个属性到
NodeVm,因为我们将更改现有对象,我们需要使用而不是 ListObservableCollection<T>以便 GUI 自动更新,并且不要忘记调用RaisePropertyChanged()可能更改的属性。现在做一个小改动来简化代码,而不是根列表,
List<NodeVM> Fields我建议有一个完整的根元素NodeVm RootNode和一些唯一的键,我会拥有它id=0,所有应该在顶层的元素(ParentId=null),我们会放入这个根元素。为了保持视图不变,只需稍微更改绑定:<TreeView ItemsSource="{Binding RootNode.Childs}">另外,我建议有一本字典
Dictionary<int, NodeVm> nodesDict,以便更容易找到所需的节点并对其进行更改。所以,让某个元素集合来找我们
List<Node> nodes,其中:然后,我的初始负载如下所示:
现在,更新时:
全部。这种方法的缺点是,如果
Node添加了新属性,您需要记住添加代码来复制它们。现在这是在两个地方完成的,但是可以(并且应该)将其移至单独的方法。