WPF TreeView,IsExpanded 的双向绑定不影响来自 C# 代码的 GUI
WPF TreeView, TwoWay binding for IsExpanded is not affecting GUI from C# code
我正在尝试创建一个可以在树层次结构中显示项目的 TreeView。我希望能够使用代码 (C#) 通过绑定到 ObservableCollection 的属性展开和折叠 TreeView 中的 TreeViewItems。
我已经将我的 class 的 属性 绑定到 IsExpanded,如果我在设置树的 ItemSource 之前设置它似乎可以工作 - 新创建的层次结构将预先展开。
但是,如果我单击为集合中的项目设置 IsExpanded 的按钮,它不会展开或折叠 GUI 中的树项目。
这是到目前为止该程序的丑陋屏幕截图。这些文件夹是在初始化过程中手动创建的。
这里是 TreeView xaml 主 window:
<TreeView x:Name="TheProjectTree" Margin="5" BorderBrush="{x:Null}" ItemsSource="{Binding DataSet}">
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="IsExpanded" Value="{Binding Path=IsExpanded, Mode=TwoWay}" />
<!--<EventSetter Event="Expanded" Handler="TheProjectTreeItem_Expanded" />-->
</Style>
</TreeView.ItemContainerStyle>
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding nodes}">
<StackPanel Orientation="Horizontal">
<Image Source="{Binding Path=Icon}" Height="16"/>
<TextBlock Text=" " />
<TextBlock Text="{Binding Path=Name}" />
<TextBlock Text=" (" />
<TextBlock Text="{Binding Path=Type}" />
<TextBlock Text=")" />
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
这是一个 MyProject class,它具有以下数据结构:
using System.Collections.ObjectModel;
namespace Project_X
{
public class MyProject
{
public ObservableCollection<MyNode> nodes;
public MyProject()
{
}
public void Initialize()
{
nodes = new ObservableCollection<MyNode>();
nodes.Add(new MyNode("Untitled Project", "Project"));
AddFolder("0. Initialize");
AddFolder("1. Reset");
AddFolder("2. Migrate");
}
public void AddFolder(string folderName)
{
nodes[0].nodes.Add(new MyProject.MyNode(folderName, "Folder"));
}
public class MyNode
{
public string Name { get; set; }
public string Type { get; set; }
public bool IsExpanded { get; set; }
public ObservableCollection<MyNode> nodes { get; set; }
public MyNode(string theName, string theType)
{
Name = theName;
Type = theType;
nodes = new ObservableCollection<MyNode>();
}
public string Icon
{
get
{
if (Type == "Project")
return "./graphics/icon_projectTree_small.png";
else if (Type == "Folder")
return "./graphics/icon_projectTree_small.png";
else if (Type == "Object")
return "./graphics/icon_projectTree_small.png";
else if (Type == "SQL")
return "./graphics/icon_projectTree_small.png";
else if (Type == "Text")
return "./graphics/icon_projectTree_small.png";
return "./graphics/icon_projectTree_small.png";
}
}
}
}
}
最后,这是一个我可以从测试按钮调用的小测试程序。
private void NewProject()
{
Project = new MyProject(); // fire up the main project variable!
Project.Initialize(); // give it some dummy data!
Project.nodes[0].IsExpanded = true; // pre-expand the top-level project node
TheProjectTree.ItemsSource = Project.nodes; // assign the data set to the tree in the main window
Project.AddFolder("test"); // this works! adding new folders to the collection will show up in the GUI
Project.nodes[0].IsExpanded = true; // this does NOT work! it should collapse the top-levl project node in the tree, but it doesn't
}
如果你能给我一些知识,我将不胜感激。我通常在 SQL 工作,C# 和 .NET 不是我的强项。我整个晚上都在努力思考 MVVM 和天哪,我现在觉得自己是一个非常糟糕的程序员!
你的 MyNode class 需要实现 INotifyPropertyChanged
让 Gui 知道 属性 已经改变。
然后在 IsExpanded 属性 的 setter 中,您将不得不调用 NotifyPropertyChanged 已在给定的 link.
中进行了解释
为您的 MyNode
Class 实现 INotifyPropertyChanged 接口。它通知 属性 值已更改。
public class MyNode : INotifyPropertyChanged
{
private bool isExpanded;
public string Name { get; set; }
public string Type { get; set; }
public bool IsExpanded
{
get => isExpanded;
set
{
isExpanded = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsExpanded)));
}
}
public ObservableCollection<MyNode> nodes { get; set; }
public MyNode(string theName, string theType)
{
Name = theName;
Type = theType;
nodes = new ObservableCollection<MyNode>();
}
public event PropertyChangedEventHandler PropertyChanged;
}
我正在尝试创建一个可以在树层次结构中显示项目的 TreeView。我希望能够使用代码 (C#) 通过绑定到 ObservableCollection 的属性展开和折叠 TreeView 中的 TreeViewItems。
我已经将我的 class 的 属性 绑定到 IsExpanded,如果我在设置树的 ItemSource 之前设置它似乎可以工作 - 新创建的层次结构将预先展开。
但是,如果我单击为集合中的项目设置 IsExpanded 的按钮,它不会展开或折叠 GUI 中的树项目。
这是到目前为止该程序的丑陋屏幕截图。这些文件夹是在初始化过程中手动创建的。
这里是 TreeView xaml 主 window:
<TreeView x:Name="TheProjectTree" Margin="5" BorderBrush="{x:Null}" ItemsSource="{Binding DataSet}">
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="IsExpanded" Value="{Binding Path=IsExpanded, Mode=TwoWay}" />
<!--<EventSetter Event="Expanded" Handler="TheProjectTreeItem_Expanded" />-->
</Style>
</TreeView.ItemContainerStyle>
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding nodes}">
<StackPanel Orientation="Horizontal">
<Image Source="{Binding Path=Icon}" Height="16"/>
<TextBlock Text=" " />
<TextBlock Text="{Binding Path=Name}" />
<TextBlock Text=" (" />
<TextBlock Text="{Binding Path=Type}" />
<TextBlock Text=")" />
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
这是一个 MyProject class,它具有以下数据结构:
using System.Collections.ObjectModel;
namespace Project_X
{
public class MyProject
{
public ObservableCollection<MyNode> nodes;
public MyProject()
{
}
public void Initialize()
{
nodes = new ObservableCollection<MyNode>();
nodes.Add(new MyNode("Untitled Project", "Project"));
AddFolder("0. Initialize");
AddFolder("1. Reset");
AddFolder("2. Migrate");
}
public void AddFolder(string folderName)
{
nodes[0].nodes.Add(new MyProject.MyNode(folderName, "Folder"));
}
public class MyNode
{
public string Name { get; set; }
public string Type { get; set; }
public bool IsExpanded { get; set; }
public ObservableCollection<MyNode> nodes { get; set; }
public MyNode(string theName, string theType)
{
Name = theName;
Type = theType;
nodes = new ObservableCollection<MyNode>();
}
public string Icon
{
get
{
if (Type == "Project")
return "./graphics/icon_projectTree_small.png";
else if (Type == "Folder")
return "./graphics/icon_projectTree_small.png";
else if (Type == "Object")
return "./graphics/icon_projectTree_small.png";
else if (Type == "SQL")
return "./graphics/icon_projectTree_small.png";
else if (Type == "Text")
return "./graphics/icon_projectTree_small.png";
return "./graphics/icon_projectTree_small.png";
}
}
}
}
}
最后,这是一个我可以从测试按钮调用的小测试程序。
private void NewProject()
{
Project = new MyProject(); // fire up the main project variable!
Project.Initialize(); // give it some dummy data!
Project.nodes[0].IsExpanded = true; // pre-expand the top-level project node
TheProjectTree.ItemsSource = Project.nodes; // assign the data set to the tree in the main window
Project.AddFolder("test"); // this works! adding new folders to the collection will show up in the GUI
Project.nodes[0].IsExpanded = true; // this does NOT work! it should collapse the top-levl project node in the tree, but it doesn't
}
如果你能给我一些知识,我将不胜感激。我通常在 SQL 工作,C# 和 .NET 不是我的强项。我整个晚上都在努力思考 MVVM 和天哪,我现在觉得自己是一个非常糟糕的程序员!
你的 MyNode class 需要实现 INotifyPropertyChanged 让 Gui 知道 属性 已经改变。 然后在 IsExpanded 属性 的 setter 中,您将不得不调用 NotifyPropertyChanged 已在给定的 link.
中进行了解释为您的 MyNode
Class 实现 INotifyPropertyChanged 接口。它通知 属性 值已更改。
public class MyNode : INotifyPropertyChanged
{
private bool isExpanded;
public string Name { get; set; }
public string Type { get; set; }
public bool IsExpanded
{
get => isExpanded;
set
{
isExpanded = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsExpanded)));
}
}
public ObservableCollection<MyNode> nodes { get; set; }
public MyNode(string theName, string theType)
{
Name = theName;
Type = theType;
nodes = new ObservableCollection<MyNode>();
}
public event PropertyChangedEventHandler PropertyChanged;
}