WPF TreeView - Как обновить дерево после добавления / удаления узла? - PullRequest
4 голосов
/ 10 февраля 2011

Я ссылаюсь на эту статью:

WPF TreeView HierarchicalDataTemplate - привязка к объекту с несколькими дочерними коллекциями

и изменение древовидной структуры следующим образом:

Root
  |__Group
       |_Entry
           |_Source

В Entry.cs:

public class Entry
{
    public int Key { get; set; }
    public string Name { get; set; }

    public ObservableCollection<Source> Sources { get; set; }

    public Entry()
    {
        Sources = new ObservableCollection<Source>();
    }

    public ObservableCollection<object> Items
    {
        get
        {
            ObservableCollection<object> childNodes = new ObservableCollection<object>();

            foreach (var source in this.Sources)
                childNodes.Add(source);

            return childNodes;
        }
    }
}

В Source.cs:

public class Source
{
    public int Key { get; set; }
    public string Name { get; set; }
}

В XAML-файле:

<UserControl.CommandBindings>
    <CommandBinding Command="New" Executed="Add" />
</UserControl.CommandBindings>

    <TreeView x:Name="TreeView">
        <TreeView.ItemContainerStyle>
            <Style TargetType="{x:Type TreeViewItem}">
                <Setter Property="TreeViewItem.IsExpanded" Value="True"/>
            </Style>
        </TreeView.ItemContainerStyle>

        <TreeView.Resources>
            <HierarchicalDataTemplate DataType="{x:Type local:Root}" ItemsSource="{Binding Items}">
                 <TextBlock Text="{Binding Path=Name}" IsEnabled="True">
                 </TextBlock>
            </HierarchicalDataTemplate>

            <HierarchicalDataTemplate DataType="{x:Type local:Group}" ItemsSource="{Binding Items}">
                <TextBlock Text="{Binding Path=Name}" IsEnabled="True">
                </TextBlock>
            </HierarchicalDataTemplate>


            <HierarchicalDataTemplate DataType="{x:Type local:Entry}" ItemsSource="{Binding Items}">
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="{Binding Path=Name}" IsEnabled="True">
                        <TextBlock.ContextMenu>
                            <ContextMenu >
                                <MenuItem Header="Add" Command="New">
                                </MenuItem>
                            </ContextMenu>
                        </TextBlock.ContextMenu>
                    </TextBlock>
                </StackPanel>
            </HierarchicalDataTemplate>


            <DataTemplate DataType="{x:Type local:Source}" >
                <TextBlock Text="{Binding Path=Name}" />
            </DataTemplate>

        </TreeView.Resources>
    </TreeView>

В UserControl.cs:

public ObservableCollection<Root> Roots = new ObservableCollection<Root>();

    public UserControl6()
    {
        InitializeComponent();

        //...Add new node manually

        TreeView.ItemsSource = Roots;
    }

    private void Add(object sender, ExecutedRoutedEventArgs e)
    {
        Entry ee = (Entry)TreeView.SelectedItem;
        Source s3 = new Source() { Key = 3, Name = "New Source" };
        ee.Sources.Add(s3);
    }

Когда я нажимаю правую кнопку на определенном узле «Запись», чтобы добавить новый узел «Источник» в разделе «Ввод» (вызов метода «Добавить»), я успешно добавляю новый объект «Источник» в разделе «Ввод»,но я не вижу этот новый узел на дереве.Как обновить дерево при добавлении / удалении узла?

Ответы [ 3 ]

6 голосов
/ 10 февраля 2011

Используйте ObservableCollection вместо IList, если вы хотите уведомить пользовательский интерфейс о том, что что-то в коллекции изменилось

0 голосов
/ 30 апреля 2019

Используйте этот класс, и любые изменения в коллекции Sources обновят / обновят дерево в пользовательском интерфейсе.

public class Entry
{
    public int Key { get; set; }
    public string Name { get; set; }

    public ObservableCollection<Source> Sources { get; set; }

    public Entry()
    {
        Sources = new ObservableCollection<Source>();
    }

    public CompositeCollection Items
    {
       get
       {
          return new CompositeCollection()
          {
             new CollectionContainer() { Collection = Sources },
             // Add other type of collection in composite collection
             // new CollectionContainer() { Collection = OtherTypeSources }
          };
       } 
    }

 }
0 голосов
/ 13 июля 2016

Насколько мне известно, изменение типа для Items на ObservableCollection<T> не решит проблему. Вам необходимо реализовать INotifyPropertyChanged. Я протестировал оба решения для своего дерева, потому что столкнулся с одной и той же проблемой. В моем случае изменение типа с IList на ObservableCollection не обновило графический интерфейс. Однако, когда я изменил свое свойство auto:

public List<SourceControlItemViewBaseModel> Items { get; set; }

до

 private IEnumerable<SourceControlItemViewBaseModel> _items;
    public IEnumerable<SourceControlItemViewBaseModel> Items
    {
        get { return _items; }
        set
        {
            _items = value;
            OnPropertyChanged();
        }
    }

А именно, я реализовал INotifyPropertyChanged, и это изменило ситуацию. Метод, который строит древовидную структуру, определяет фактический тип Items как новый List<T>(), но он работает и обновляет графический интерфейс. Тем не менее, мое дерево было построено в чистом виде MVVM без использования кода. Я использую

<TreeView ItemsSource="{Binding SourceControlStructureItems}" />

и в используемой модели вида:

  currentVm.Items= await SourceControlRepository.Instance.BuildSourceControlStructureAsync(currentVm.ServerPath);

Это означает, что я не добавил / не удалил элементы, но перестроил подсборку Node.

...