C# WPF树视图子项未显示
我试图通过在代码中创建并添加我的C# WPF树视图子项未显示,c#,wpf,treeview,C#,Wpf,Treeview,我试图通过在代码中创建并添加我的TreeView项来构建TreeView。我有一个文件夹对象,其中包含子文件夹列表和会话列表。所有这些都保存在根文件夹对象中。当我使用递归创建TreeViewItems并将它们添加到我的TreeView中时,根文件夹中的文件夹和会话将出现,但不显示属于它们集合的TreeViewItems 当我手工为页面写出xaml时,它会按需要显示,但在添加代码时不会显示。我已经查看了调试器中的TreeView对象,我可以看到Items集合中的treeviewmes的第二层和第三
TreeView项来构建TreeView
。我有一个文件夹
对象,其中包含子文件夹列表和会话列表
。所有这些都保存在根文件夹对象中。当我使用递归创建TreeViewItems
并将它们添加到我的TreeView
中时,根文件夹中的文件夹和会话将出现,但不显示属于它们集合的TreeViewItems
当我手工为页面写出xaml时,它会按需要显示,但在添加代码时不会显示。我已经查看了调试器中的TreeView
对象,我可以看到Items
集合中的treeviewmes
的第二层和第三层,但它们都没有显示出来
我的物品
[Serializable]
public class Session
{
public int Id { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public Protocol ConnectionProtocol { get; set; }
public int Port { get; set; }
}
[Serializable]
public class Folder
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual int ParentID { get; set; }
public virtual List<Folder> SubFolders { get; set; } = new List<Folder>();
public virtual List<Session> Sessions { get; set; } = new List<Session>();
}
[Serializable]
public class Root : Folder
{
public KeyValuePair<ulong, int> Version
{
get
{
return new KeyValuePair<ulong, int>(_revisionNumber, GetHashCode());
}
}
private ulong _revisionNumber = 0;
public override int Id { get => 0; set { } }
public override int ParentID { get => 0; set { } }
private void UpdateVersion()...
public bool AddSession(Session session)...
public bool RemoveSession(Session session)...
public bool AddFolder(Folder folder)...
public bool RemoveFolder(Folder folder)...
}
我希望有一棵树能像……这样显示出来
v {} Folder 1
v {} SubFolder 1
[] Session
[] Session
> {} SubFolder 2
[] Session
> {} SubFolder 3
> {} Folder 2
> {} Folder 3
[] Session
[] Session
[] Session
但我得到的是
v {} Folder 1
v {} Folder 2
v {} Folder 3
[] Session
[] Session
[] Session
如果项不包含至少一个子项,则TreeView
或实际节点将无法展开。如果以后需要将子项添加到树中(例如,延迟加载),则需要添加虚拟项以使TreeView
显示扩展程序。由于您使用的是列表
作为子集合,因此必须首先创建完整的树数据结构,并立即将其添加到树视图.ItemSource
中,或者只需使用可观察集合
为了保持简单,所有节点类型都应该存储在一个需要公共基类型的共享集合中。然后,您可以简单地使用DataTemplateSelector
动态创建相应的treevieItem
main window.xaml
<Window>
<Window.DataContext>
<ViewModel />
</Window.DataContext>
<TreeView ItemsSource="{Binding Folders}"
ItemTemplateSelector="{DynamicResource DataTemplateSelector}">
<TreeView.Resources>
<local:DataTemplateSelector x:Key="DataTemplateSelector" />
<HierarchicalDataTemplate x:Key="FolderDataTemplate"
DataType="Folder"
ItemsSource="{Binding ChildItems}">
<TextBlock Text="{Binding Name}" />
</HierarchicalDataTemplate>
<DataTemplate x:Key="SessionDataTemplate"
DataType="Session">
<TextBlock Text="{Binding Name}" />
</DataTemplate>
</TreeView.Resources>
</TreeView>
</Window>
ViewModel.cs
class DataTemplateSelector : System.Windows.Controls.DataTemplateSelector
{
public override DataTemplate
SelectTemplate(object item, DependencyObject container)
{
FrameworkElement element = container as FrameworkElement;
return item is Session
? element.FindResource("SessionDataTemplate") as DataTemplate
: element.FindResource("FolderDataTemplate") as DataTemplate;
}
}
class ViewModel
{
public ObservableCollection<Folder> Folders { get; set; }
public ViewModel()
{
this.Folders = new ObservableCollection<Folder>
{
new Folder("Folder_1")
{
ChildItems = new ObservableCollection<TreeItem>
{
new Folder("Folder_1.1")
{
ChildItems = new ObservableCollection<TreeItem>
{
new Folder("Folder_1.1.1")
{
ChildItems = new ObservableCollection<TreeItem>
{
new Session("SessionA"),
new Session("SeesionB")
}
},
new Session("SessionA"),
new Session("SeesionB")
}
},
new Folder("Folder_1.2")
{
ChildItems = new ObservableCollection<TreeItem>
{
new Session("SessionA"),
new Session("SeesionB")
}
}
}
}
};
}
}
类视图模型
{
公共ObservableCollection文件夹{get;set;}
公共视图模型()
{
this.Folders=新的ObservableCollection
{
新文件夹(“文件夹1”)
{
ChildItems=新的ObservableCollection
{
新文件夹(“文件夹1.1”)
{
ChildItems=新的ObservableCollection
{
新文件夹(“文件夹_1.1.1”)
{
ChildItems=新的ObservableCollection
{
新一届会议(“会期A”),
新会议(“见附件B”)
}
},
新一届会议(“会期A”),
新会议(“见附件B”)
}
},
新文件夹(“文件夹1.2”)
{
ChildItems=新的ObservableCollection
{
新一届会议(“会期A”),
新会议(“见附件B”)
}
}
}
}
};
}
}
数据项层次结构
public abstract class TreeItem
{
public TreeItem(String name)
{
this.Name = name;
}
public string Name { get; set; }
}
public class Folder : TreeItem
{
public Folder(string name) : base(name)
{
}
public ObservableCollection<TreeItem> ChildItems { get; set; } = new ObservableCollection<TreeItem>();
}
public class Session : TreeItem
{
public Session(string name) : base(name)
{
}
}
公共抽象类树项
{
公共树项(字符串名称)
{
this.Name=Name;
}
公共字符串名称{get;set;}
}
公共类文件夹:TreeItem
{
公用文件夹(字符串名称):基(名称)
{
}
公共ObservableCollection子项{get;set;}=new ObservableCollection();
}
公开课:TreeItem
{
公共会话(字符串名称):基(名称)
{
}
}
如果您正在使用WPF,那么为什么要在代码隐藏中创建控件?控件应创建为XAML。你构建TreeView的方法是完全错误的。这对我使用HierarchycalDataTemplate
非常有帮助,但我仍然在视图模型上苦苦挣扎。我应该更清楚地了解用户定义的文件夹层次结构和会话。我无法预加载树,因为我没有设置文件夹结构,但不需要延迟加载。我是否应该在每次添加或删除项目时重新创建整个TreeView
。只需将列表
替换为ObservableCollection
,即可让树视图在数据结构被修改(项目被添加、删除或移动)时自动更新自身。我对“HierarchicalDataTemplate”做了更多的研究,而我缺少的是共享继承和ViewModel。谢谢你的帮助!
public abstract class TreeItem
{
public TreeItem(String name)
{
this.Name = name;
}
public string Name { get; set; }
}
public class Folder : TreeItem
{
public Folder(string name) : base(name)
{
}
public ObservableCollection<TreeItem> ChildItems { get; set; } = new ObservableCollection<TreeItem>();
}
public class Session : TreeItem
{
public Session(string name) : base(name)
{
}
}