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