【问题标题】:WPF - TreeView adding Children to Children completly dynamicallyWPF - TreeView 完全动态地将子项添加到子项
【发布时间】:2014-10-17 14:29:05
【问题描述】:

我已经在 WinForms 中构建了一个完整的工作逻辑,用于在来自数据库的 TreeView 中插入数据,所以我不能只在树视图后面放置一个数据表并感到高兴,因为我需要构建节点、下节点和下节点等. 旧 WinForms 中的工作代码:

    private void waregroup()
    {
        DataSet myDataSet = new DataSet();
        DataTable myDataTable = new DataTable();
        string sqlStatement = "SELECT * FROM APWGRUPP ORDER BY WG_WGSCHL ASC";
        string str_key = "";
        string str_desc = "";
        int int_node0 = 0;
        int int_node1= 0;
        int int_node2 = 0;
        int int_node3 = 0;
        int int_node4 = 0;

        myDataSet = ImportDBF(sqlStatement);
        myDataTable = myDataSet.Tables["Table"];
        foreach (DataRow row in myDataTable.Rows)
        {
            str_desc = row.Field<string>(1);
            str_key = row.Field<string>(2);
            switch (str_key.Length)
            {
                case 1:
                    trv_waregroup.Nodes.Add(str_key + "-" + str_desc);
                    int_node0++;
                    int_node1 = 0;
                    int_node2 = 0;
                    int_node3 = 0;
                    int_node4 = 0;
                    break;
                case 2:
                    trv_waregroup.Nodes[int_node0 - 1].Nodes.Add(str_key + "-" + str_desc);
                    int_node1++;
                    int_node2 = 0;
                    int_node3 = 0;
                    int_node4 = 0;
                    break;
                case 4:
                    trv_waregroup.Nodes[int_node0 - 1].Nodes[int_node1 - 1].Nodes.Add(str_key + "-" + str_desc);
                    int_node2++;
                    int_node3 = 0;
                    int_node4 = 0;
                    break;
                case 5:
                    trv_waregroup.Nodes[int_node0 - 1].Nodes[int_node1 - 1].Nodes[int_node2 - 1].Nodes.Add(str_key + "-" + str_desc);
                    int_node3++;
                    int_node4 = 0;
                    break;
                case 6:
                    trv_waregroup.Nodes[int_node0 - 1].Nodes[int_node1 - 1].Nodes[int_node2 - 1].Nodes[int_node3 - 1].Nodes.Add(str_key + "-" + str_desc);
                    int_node4++;
                    break;
                default:
                    trv_waregroup.Nodes[int_node0 - 1].Nodes[int_node1 - 1].Nodes[int_node2 - 1].Nodes[int_node3 - 1].Nodes[int_node4 - 1].Nodes.Add(str_key + "-" + str_desc);
                    break;
            }
        }
    }

现在我不能再使用 Items[Counter].Add 的逻辑了,但我能想到的唯一可能的解决方案是使用枚举。但我发现的只是使用 Header 作为新项目来添加新节点。

我尝试过这种方式,但没有得到可用的项目:

TreeViewItem temp = (TreeViewItem)_WareGroups.Items.GetItemAt(Node0 - 1);
_WareGroups.Items.Add(GroupKey + "-" + GroupDesc);

有人知道如何以这种方式添加近 2500 件物品吗?

【问题讨论】:

  • 如果这是 WPF,请立即删除所有可怕的代码并开始阅读 herehere
  • 基本上,您不会在 WPF 的程序代码中“将节点添加到 TreeView”或“创建 TreeViewItems”或类似的东西。相反,您将创建一个适合HierarchicalDataTemplate 使用的正确Hierarchical Data Structure。顺便说一句,强烈建议您至少对分层有最低限度的尊重,并将与 DB 相关的代码移出 UI 层。
  • 请在方法名称上使用正确的大小写。应该是WareGroup(),如果有的话。
  • 不,它是 WinForms,我使用的是旧的 VisualBasic 知识。我将其转交给 WPF,并且在我新创建的代码中使用了正确的 camelCase 和 PascalCase。但是 MVVM 对我来说是一本有 7 个印章的书,即我没有任何关于如何使用 DataBindings 的计划,a.s.o。但我正在努力学习它。您的链接可能会有所帮助,但他们需要时间来学习我想我没有。但这就是生活的方式,嗯? :)
  • 您可以 A) 花一些时间学习如何正确使用 WPF,或者您可以 B) 花两倍的时间试图将一种陈旧的、不充分的程序方法强加到一个设计合理的框架中那样用的。无论哪种方式,您都会花时间,但选项 A 似乎可以让您真正学到东西。

标签: c# wpf winforms treeview


【解决方案1】:

好的,我找到了解决方案。如果有人感兴趣:

XAML:

<TreeView ItemsSource="{Binding Items}" Height="{Binding ElementName=AdminConsoleWindow, Path=ActualHeight, Converter={StaticResource MathConverter}, ConverterParameter=(@VALUE/3)}">
  <TreeView.ItemTemplate>
    <HierarchicalDataTemplate ItemsSource="{Binding SubItems}">
      <TextBlock Text="{Binding Header}"/>
    </HierarchicalDataTemplate>
  </TreeView.ItemTemplate>
</TreeView>

代码隐藏:

public partial class AdminConsole : Window
{
    public ObservableCollection<MyItem> Items { get; set; }

    public AdminConsole()
    {
        this.Items = new ObservableCollection<MyItem>();
        this.DataContext = this;
        InitializeComponent();
    }

    private void AddWareGroups()
    {
        DataTable MyTable = DBase.GetWareGroups();
        foreach (DataRow MyRow in MyTable.Rows)
        {
            string ItemDescription = MyRow.Field<string>(1);
            string ItemKey = MyRow.Field<string>(2);
            MyItem NewItem = new MyItem();
            NewItem.Header = ItemKey + " - " + ItemDescription;
            if (ItemKey.Length == 1)
            {
                this.Items.Add(NewItem);
            }
            else if (ItemKey.Length == 2 || ItemKey.Length == 5 || ItemKey.Length == 6)
            {
                IterateSubItems(1, NewItem, ItemKey, this.Items);
            }
            else // if (ItemKey.Length == 4 || ItemKey.Length == 8)
            {
                IterateSubItems(2, NewItem, ItemKey, this.Items);
            }
        }
    }

    private void IterateSubItems(int shortenLength, MyItem newItem, string itemKey, ObservableCollection<MyItem> myCollection)
    {
        foreach (MyItem ItemChild in myCollection)
        {
            if (ItemChild.Header.Substring(0, ItemChild.Header.IndexOf(" - ")).Equals(itemKey.Substring(0, itemKey.Length - shortenLength)))
            {
                ItemChild.SubItems.Add(newItem);
                return;
            }
            else
            {
                if (ItemChild.SubItems.Count > 0)
                {
                    IterateSubItems(shortenLength, newItem, itemKey, ItemChild.SubItems);
                }
            }
        }
    }

在一个额外的类中:

public class MyItem : INotifyPropertyChanged
{
    #region INotifyPropertyChanged Members
    protected void OnPropertyChanged(string propertyName)
    {
        var evt = this.PropertyChanged;
        if (evt != null)
            evt(this, new PropertyChangedEventArgs(propertyName));
    }
    public event PropertyChangedEventHandler PropertyChanged;
    #endregion

    private string _Header = "Item";
    public string Header
    {
        get
        {
            return this._Header;
        }
        set
        {
            if (this._Header != value)
            {
                this._Header = value;
                this.OnPropertyChanged("Header");
            }
        }
    }
    private ObservableCollection<MyItem> _SubItems = new ObservableCollection<MyItem>();
    public ObservableCollection<MyItem> SubItems
    {
        get
        {
            return this._SubItems;
        }
        set
        {
            if (this._SubItems != value)
            {
                this._SubItems = value;
                this.OnPropertyChanged("SubItems");
            }
        }
    }
}

【讨论】:

    【解决方案2】:

    类似的东西:

    foreach (DataRow row in myDataTable.Rows)
    {
      str_desc = row.Field<string>(1);
      str_key = row.Field<string>(2);
    
      TreeNode node = new TreeNode(str_key + "-" + str_desc);
    
      int lvl = 1;
    
      addToLvl(lvl, trv_waregroup, trv_waregroup.Nodes[trv_waregroup.GetNodeCount(false) - 1], str_key.Length, node);
    
    }
    
    public void addToLvl(int actualLvl, TreeView tv, TreeNode last, int lvlToReach, TreeNode nodeToAdd)
    {
      if (actualLvl == lvlToReach)
        last.Add(node); //wpf ?? last.Nodes.Add(node);
      else
        addToLvl(actualLvl++, tv, last.LastNode, lvlToreach, nodeToAdd);
    }
    

    【讨论】:

    • last.Nodes 在 WPF 中不再存在,它现在是 items.add,但不再存在 Nodes[2].Nodes[5].Nodes.Add。那是我的问题。
    • 我想说是的,但是您使用类似 trv_waregroup.Nodes[trv_waregroup.GetNodeCount(false) - 1] 的东西,并且不再起作用。您不能再处理每个索引的节点了。
    猜你喜欢
    • 2013-07-16
    • 2010-09-26
    • 2017-03-27
    • 1970-01-01
    • 1970-01-01
    • 2015-03-18
    • 2020-01-08
    • 2016-08-12
    • 1970-01-01
    相关资源
    最近更新 更多