Добавление дочернего узла в середине списка других дочерних узлов

Этот вопрос является продолжением этого вопроса. По сути, я хочу добавить узлы к моему 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));

XAML TreeView (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}" />

Данные и свойства ObservableCollection<HierarchicalVM>, к которым привязан TreeView:

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

person Eric after dark    schedule 10.03.2014    source источник
comment
Поскольку это WPF, почему ваше древовидное представление не привязано к коллекции, и в этом случае вы могли бы использовать функцию InsertAt коллекции? Вручную возиться со списком детей, как правило, не очень хорошая идея.   -  person BradleyDotNET    schedule 11.03.2014
comment
Подождите, это связано с коллекцией, может быть, я просто использую неправильный подход.   -  person Eric after dark    schedule 11.03.2014
comment
Да, он должен быть привязан к ObservableCollection, и вы хотите изменить его, а не дочерние элементы визуального элемента.   -  person BradleyDotNET    schedule 11.03.2014
comment
Итак, node.Children.Add() - это неправильный способ добавления дочернего узла? Как тогда правильно добавить детей?   -  person Eric after dark    schedule 11.03.2014
comment
Ваш XAML должен быть связан таким образом, чтобы вы просто меняли базовую коллекцию, и она распространялась вверх. Можете ли вы опубликовать свой XAML и любой связанный код ViewModel?   -  person BradleyDotNET    schedule 11.03.2014
comment
Я разместил XAML TreeView. Думаю, мне просто нужно знать правильные операции для использования в коллекции.   -  person Eric after dark    schedule 11.03.2014
comment
Пожалуйста, дайте мне знать, что еще вы хотели бы увидеть, если что.   -  person Eric after dark    schedule 11.03.2014
comment
У вас есть иерархический шаблон данных или код данных, который я мог бы увидеть? Вам нужна функция InsertAt, но мой пример будет не очень хорошим, если вы не знаете, как выглядят данные.   -  person BradleyDotNET    schedule 11.03.2014
comment
Да, ObservableCollection относится к типу ViewModel. Я опубликую то, что я думаю, что вы ищете.   -  person Eric after dark    schedule 11.03.2014
comment
Дайте мне знать, если мой ответ поможет! По крайней мере, это должно сблизить вас.   -  person BradleyDotNET    schedule 12.03.2014


Ответы (1)


Хорошо, если у вас уже есть ссылка на родительский объект (а не на элемент пользовательского интерфейса DataTreeItem), я могу придумать два способа сделать это. Это не пришло мне в голову с небольшой проверкой на 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, который содержит коллекцию дочерних элементов, например:

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

Теперь у нас есть коллекция Parent с именем Data в модели представления, к которой привязан TreeView. Каким-то образом мы получаем единственный экземпляр этого родительского класса (который определенно не должен быть пустым, тот факт, что ваш объект «node.Children» должен быть ОГРОМНЫМ красным флагом).

Если вы согласны с тем, что я сказал выше, код вставки, который я разместил, должен работать.

Пожалуйста, дайте мне знать, если я могу уточнить или добавить к этому ответу или помочь каким-либо другим образом.

person BradleyDotNET    schedule 11.03.2014
comment
Хорошо, я пытаюсь использовать это решение, но мне нужно использовать node.Children во всех областях, которые у вас есть Children. При использовании этого я получаю сообщение об ошибке: Operator '.' cannot be applied to operand of type 'void'. (использую первый вариант) - person Eric after dark; 13.03.2014
comment
@Ericafterdark, прошу прощения за неясность. Вам нужна ссылка на родителя, и вы хотите использовать свойство Children этого объекта. Я обновил свой ответ, чтобы отразить это. - person BradleyDotNET; 13.03.2014
comment
У меня есть ссылка на родителя, и я считаю, что использую его точно так же. Пожалуйста, взгляните на мое обновление вопроса, я добавил свою текущую попытку решения. - person Eric after dark; 13.03.2014
comment
В коде, который вы разместили, что такое данные? Похоже, вы все еще ищете визуальное дерево. Все это есть только в связанных коллекциях. - person BradleyDotNET; 13.03.2014
comment
Данные — это полный TreeView, узел — это та часть, с которой я работаю. Данные объявляются так: public ObservableCollection<Type> Data { get; set; } - person Eric after dark; 13.03.2014
comment
Обновлено, чтобы попытаться обойти это, дайте мне знать, что вы думаете - person BradleyDotNET; 13.03.2014
comment
Итак, если node.Children недействительно, правильно ли будет спросить вас, как изменить его, чтобы оно не было недействительным? - person Eric after dark; 13.03.2014
comment
давайте продолжим обсуждение в чате - person BradleyDotNET; 13.03.2014