【问题标题】:Adding a child node in the middle of a list of other children在其他子节点列表的中间添加一个子节点
【发布时间】:2014-03-10 21:54:09
【问题描述】:

这个问题是this question 的后续问题。基本上我想做的是以数字顺序将节点添加到我的treeView。现在我正在处理一个子节点列表。每个孩子都有一个DisplayName 的数值。在我的程序中,我有一个循环来检查要添加的节点是否有一个DisplayName 小于循环中当前子节点的DisplayName。如果新孩子的DisplayName 小于正在检查的孩子,我想在已经存在的节点之前添加新节点。我很难找到一种方法来做到这一点。

这是我的代码:

var node = Data.GetAllChildren(x => x.Children).Distinct().ToList().First(x => x.identify == 'B');

//Get # of children -- if children exist
if (node.Children.Count() > 0)
{
    newChildTitle = int.Parse(nodeName.Value); //node to add

    for (int i = 0; i < node.Children.Count(); i++)
    {
        currentChildTitle = int.Parse(node.Children.ElementAt(i).DisplayName.Value); //current node value

        if (newChildTitle == currentChildTitle) //Check if location already exists
        {
            MessageBox.Show("Sorry, that location name already exists under this category.", "Duplicate Location Name", MessageBoxButton.OK, MessageBoxImage.Warning);
            break;
        }
        else if (newChildTitle < currentChildTitle) //If new location value is less, add before current location in Tree
        {
            //CODE WOULD GO HERE**        
            break;
        }
    }
}
else //if no children exist, just add
    node.Children.Add(CreateBlockingLocation(model, blockTreeCollection, nodeName));

TreeView 的 XAML(TreeView 绑定到 ObservableCollection):

<!-- Tree view items & Functions -->
    <TreeView Name="Tree_One" IsEnabled="{Binding DataContext.DataTreeEnabled, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" ItemsSource="{Binding DataTree.Data}" />

TreeView 绑定到的ObservableCollection&lt;HierarchicalVM&gt; 的数据和属性:

private HierarchicalVM _parent;
private ObservableCollection<HierarchicalVM> _children;

public HierarchicalVM()
{
    Commands = new ObservableCollection<Command>();
}

//Relationship Properties
public HierarchicalVM Parent
{
    get { return _parent; }
    set
    {
        _parent = value;
        NotifyPropertyChange(() => Parent);
    }
}
public ObservableCollection<HierarchicalVM> Children
{
   get { return _children ?? (_children = new ObservableCollection<HierarchicalVM>()); }
   set { _children = value; }
}

当前解决方案尝试:

//Gets parent item (Data is the complete Tree)
var node = Data.GetAllChildren(x => x.Children).Distinct().ToList().First(x => x.identify == 'B'); 

if (!node.Children.Any(n => n.numValue == newNumValue))
{
    //Error is on this line: **Operator '.' cannot be applied to operand of type 'void'
    node.Children = node.Children.Add(newNode).Orderby(n => n.numValue);
}

【问题讨论】:

  • 既然是WPF,为什么你的treeview没有绑定到一个集合,在这种情况下你可以使用集合的InsertAt函数呢?手动弄乱 with children 列表通常不是一个好主意。
  • 等等,它绑定到一个集合,也许我只是采取了错误的方法。
  • 是的,它应该绑定到一个 ObservableCollection,并且你想修改它,而不是可视元素的子元素。
  • 那么node.Children.Add()不是添加子节点的正确方法吗?那么添加孩子的正确方法是什么?
  • 您的 XAML 应该以这样一种方式绑定,即您只需更改基础集合并向上传播。您可以发布您的 XAML 和任何相关的 ViewModel 代码吗?

标签: c# wpf treeview nodes children


【解决方案1】:

好的,假设您已经引用了 Parent 对象(不是 DataTreeItem UI 元素),我可以想到两种方法来完成此操作。对 MSDN 进行了一些检查,这让我无法理解,因此对于任何错误,我深表歉意。

Parent parent = //however you are getting the parent
if (!parent.Children.Any(n => n.DisplayName == newNode.DisplayName))
{
   parent.Children.Add(newNode)
   parent.Children = new ObservableCollection<ViewModel>(parent.Children.OrderBy(n => n.DisplayName));
   //OR,
   parent.Children.InsertItem(parent.Children.IndexOf(parent.Children.OrderBy(n => n.DisplayName).Last(n => n.DisplayName < newNode.DisplayName)), newNode);
}

第一种方法只是添加新项目并重新排序列表,这将获得与就地插入相同的结果。第二个实际上是就地插入,但更复杂,因为您必须找到要插入的索引。

如果列表已经排序,您可以在第二种方法中删除 OrderBy。这也假设 DisplayName 是一个 int 和每个子节点的属性(从您发布的代码中它不是,但它应该是)。

显然我不了解你的架构,所以我将解释我认为应该如何,然后也许你可以发现你的代码在哪里被破坏了。

我们有一个名为 Parent 的对象类型,其中包含一个名为 children 的集合,如下所示:

class Parent<T>
{
   ObservableCollection<T> Children;
}

现在我们在 TreeView 绑定到的视图模型中有一个称为 Data 的 Parent 集合。不知何故,我们得到了这个 Parent 类的一个实例(它绝对不应该是无效的,你的“node.Children”对象应该是一个巨大的危险信号)。

如果你同意我上面所说的,我发布的插入代码应该可以工作。

如果我可以澄清或补充此答案,或以任何其他方式提供帮助,请告诉我。

【讨论】:

  • 好的,我正在尝试使用此解决方案,但我必须在您拥有Children 的所有区域中使用node.Children。使用它时,我收到错误:Operator '.' cannot be applied to operand of type 'void'。 (我使用的是第一个选项)
  • @Ericafterdark,我很抱歉不清楚。您需要对父对象的引用,并且您想使用该对象的 Children 属性。我已经更新了我的答案以反映这一点。
  • 我引用了父级,并且我相信我以完全相同的方式使用它。请查看我的问题更新,我已经添加了我当前的解决方案尝试。
  • 在您发布的代码中,Data 是什么?听起来您仍在搜索可视化树。所有这些都只是在绑定集合中。
  • 数据是完整的TreeView,节点是我正在使用的部分。数据声明如下:public ObservableCollection&lt;Type&gt; Data { get; set; }
猜你喜欢
  • 1970-01-01
  • 2014-02-01
  • 1970-01-01
  • 2019-03-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多