通过动态WPF Treeview项目进行迭代

时间:2018-03-21 16:42:44

标签: c# wpf treeview

所以,我希望用户能够自己构建一个树视图 树视图基本上包含两种项目:

  • 项目(MenuItem继承TreeviewMenuItem
  • 子菜单(MenuSubmenu继承TreeviewMenuItem,包含List<MenuItem>

Treeview使用 ItemsSource ,这是List<TreeviewMenuItem>

用户可以将子菜单和项目添加到子菜单中 节点级别没有限制。

public abstract class TreeviewMenuItem
{
    public virtual string Text { get; set; }
    public virtual string DisplayName { get => Text; }
    public virtual MenuSubmenu ParentMenu { get; set; } = null;
}

public class MenuSubmenu : TreeviewMenuItem
{
    public override string DisplayName { get => Text + " [" + Items.Count + "]"; }
    public List<MenuItem> Items { get; set; }

    public MenuSubmenu(MenuSubmenu parent = null)
    {
        ParentMenu = parent;
        Items = new List<MenuItem>();
    }
}

public class MenuItem : TreeviewMenuItem
{
    public MenuItem(MenuSubmenu parent = null)
    {
        ParentMenu = parent;
    }
}

以下是用户可以创建的菜单示例: The menu

当用户构建完树视图后,它可以将其导出为XML 问题是:我如何遍历所有节点?

正如您所看到的,由于我的子菜单包含List<MenuItem>,其中也可以包含子菜单(等),因此我无法通过ItemsSource使用简单的循环。

我不知道如何处理动态数量的子菜单及其包含的所有项目......

2 个答案:

答案 0 :(得分:3)

要分析树,最简单的方法可能是编写递归方法。 像这样:

    public void AnalyzeTree(List<TreeviewMenuItem> menuItems)
    {
        foreach (var menuItem in menuItems)
        {
            switch (menuItem)
            {
                case MenuSubmenu submenu:
                    // TODO: submenu action
                    AnalyzeTree(submenu.Items);
                    break;
                case MenuItem item:
                    // TODO: item action
                    break;
            }
        }
    }

答案 1 :(得分:1)

第一个问题,为什么需要迭代项目?只需获取树的基础并序列化它,XML序列化将处理所有子项。 为所有派生类添加XmlInclude属性并使用XmlIgnore省略循环非常重要 在你的例子中:

 [XmlInclude(typeof(MenuSubmenu))]
 [XmlInclude(typeof(MenuItem))]
 public abstract class TreeviewMenuItem
{ 
    public virtual string Text { get; set; }
    public virtual string DisplayName { get => Text; }
    [XmlIgnore]
    public virtual MenuSubmenu ParentMenu { get; set; } = null;
}

public class MenuSubmenu : TreeviewMenuItem
{        
    public override string DisplayName { get => Text + " [" + Items.Count + "]"; }       
          [XmlArrayItem(Type = typeof(TreeviewMenuItem)),   
           XmlArrayItem(Type = typeof(MenuSubmenu))] 
    public List<MenuItem> Items { get; set; }

    public MenuSubmenu(MenuSubmenu parent = null)
    {
        Items = new List<MenuItem>();
    }
}
public class MenuItem : TreeviewMenuItem
{
    public MenuItem(MenuSubmenu parent = null)
    {
        ParentMenu = parent;
    }
}