Обновите TreeView после изменения элементов в коде - PullRequest
0 голосов
/ 17 октября 2018

Я столкнулся с проблемой.Я создал TreeView в коде позади с различными этапами TreeViewItem.Я добавил ContextMenu с функцией «Добавить элемент».Когда я вызываю эту функцию, я создаю новый элемент и добавляю его в TreeView.Проблема в том, что мнение никогда не изменится.Я уверен, что новый элемент принадлежит списку TreeViewItem (я посмотрел с отладкой).Я пробовал:

tree.Items.Refresh 

, а также:

this.UpdateLayout();

Есть мой код:

public void FillTree(TreeView tree, ObservableCollection<MyObject> nodes)
    {
        tree.Items.Clear();
        TreeViewItem Items= new TreeViewItem();
        Items.Header = "Items";
        TreeViewItem Item1;
        TreeViewItem Item2;
        for (int i = 0; i < nodes.Count; i++)
        {
            Item1 = new TreeViewItem();
            Item1.Header = nodes[i].Name;
            if(nodes[i].list != null && nodes[i].list.Count>0)
            {
                for(int j = 0; j < nodes[i].list.Count; j++)
                {
                     Item2 = new TreeViewItem();
                     Item2.Header = nodes[i].list[j].Name;
                     Item1.Items.Add(Item2);
                 }
             }
             Items.Items.Add(Items1);
        }
        tree.Items.Add(Items);
    }

Когда я нажимаю на кнопку «Подтвердить», он запускаетсяэта функция:

public void ActionButtonAddRD(object sender, RoutedEventArgs e)
    {
        FillTree(this.tree, this.nodes);
    }

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

Заранее спасибо

Ответы [ 2 ]

0 голосов
/ 17 октября 2018

Эта проблема легко решается с помощью использования шаблонизирующей функциональности WPF, а не путем создания всего пользовательского интерфейса в коде.

У вас уже есть наблюдаемая коллекция элементов, поэтому просто установите ItemsSource для TreeViewк этому.Внутри дерева используйте HierachicalDataTemplate, чтобы указать способ отображения каждого элемента.

<TreeView.Resources>
    <HierarchicalDataTemplate DataType="{x:Type MyObject}"
                              ItemsSource="{Binding list}">
        <TextBlock Text="{Binding Name}" />
    </HierarchicalDataTemplate>
</TreeView.Resources>

Обратите внимание, что список и имя должны быть открытыми свойствами (а не полями) вашего класса MyObject.

ThisТаким образом, вы можете иметь столько вложенных уровней элементов, сколько вам нужно, вместо того, чтобы ограничиваться только двумя подуровнями, которые будет поддерживать ваш код.

Если список также является наблюдаемой коллекцией, и Имя (и любойдругие свойства, которые вы хотите отобразить) реализуйте шаблон INotifyPropertyChanged, тогда отображение TreeView будет автоматически обновляться после любых изменений элемента MyObject, не требуя дальнейшей обработки.

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

0 голосов
/ 17 октября 2018

Чтобы переместить вышеупомянутое в структуру, которая обеспечивает надлежащую привязку данных, вам нужно добавить следующее свойство в ваш класс DataContext:

public ObservableCollection<TreeViewItemContext> Collection { get => this._Collection; set { this._Collection = value; this.RaisePropertyChanged(); } }
private ObservableCollection<TreeViewItemContext> _Collection;

Класс TreeViewItemContext должен выглядеть следующим образом:разрешить итерацию по всем элементам:

public class TreeViewItemContext
{
    public ObservableCollection<TreeViewItemContext> Children { get; }
    public MyObject Wrapped { get; }

    /* Other properties etc. go in here. */

    public TreeViewItemContext(MyObject wrapped)
    {
        this.Children = new ObservableCollection<TreeViewItemContext>();
        this.Wrapped = wrapped;
    }

    public IEnumerable<TreeViewItemContext> IterateTree()
    {
        yield return this;
        foreach (var tvic in this.Children)
        {
            foreach (var it in tvic.IterateTree())
            {
                yield return it;
            }
        }
    }
}

, в то время как ваш код XAML будет таким простым:

<TreeView ItemsSource="{Binding Collection}">
    <TreeView.ItemContainerStyle>
        <Style TargetType="{x:Type TreeViewItem}>
            <Setter Property="Header" Value="{Binding Wrapped.Name}"/>
        </Style>
    </TreeView.ItemContainerStyle>
    <TreeView.Resources>
        <HierarchialDataTemplate ItemsSource="{Binding Children}">
            <!-- Your DataTemplate-Content Goes In Here -->
        </HierarchialDataTemplate>
    </TreeView.Resources>
</TreeView>

Чтобы затем выполнить итерацию по всем элементам в TreeView, вам просто нужно сделатьCollection.SelectMany((it) => it.IterateTree()) в вашем основном объекте DataContext и покончим с ним.

Выполнение этого также позволит вам «просто» обновить коллекцию, добавляя / удаляя элементы из нее или просто создавая новуюодин.

метод RaisePropertyChanged кстати.всегда так:

public class AnyClass : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    protected void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName]string callee = "") => this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(callee));
    //...
}

Все ваши проблемы с обновлением исчезнут.

...