Синхронизация WPF Treeview и ListBox - PullRequest
       21

Синхронизация WPF Treeview и ListBox

0 голосов
/ 13 октября 2009

У меня есть древовидная структура, которая показывает иерархию элементов, где у каждого элемента есть флажок. Я хотел бы показать под деревом список со всеми отмеченными пунктами. Как добиться такой функциональности, используя шаблон MVVM?

Заранее спасибо Лукаш Глаз

1 Ответ

1 голос
/ 13 октября 2009

Вот пример:

ViewModel

public class TreeNodeViewModel : ViewModelBase
{
    #region Constructors

    public TreeNodeViewModel(string text, params TreeNodeViewModel[] nodes)
        : this(text, new ObservableCollection<TreeNodeViewModel>(nodes))
    {
    }

    public TreeNodeViewModel(string text, ObservableCollection<TreeNodeViewModel> nodes)
    {
        Text = text;
        Nodes = nodes;
        foreach (var node in Nodes)
        {
            node.Parent = this;
        }
        Nodes.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(Nodes_CollectionChanged);
    }

    #endregion

    #region Private methods

    private void Nodes_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        foreach (var node in e.OldItems.Cast<TreeNodeViewModel>())
        {
            node.Parent = null;
        }
        foreach (var node in e.NewItems.Cast<TreeNodeViewModel>())
        {
            node.Parent = this;
        }
        OnPropertyChanged("CheckedNodes");
    }

    private void NotifyParent()
    {
        if (Parent != null)
        {
            Parent.OnPropertyChanged("CheckedNodes");
            Parent.NotifyParent();
        }
    }

    #endregion

    #region Private data

    private string _text;
    private bool _isChecked;
    private TreeNodeViewModel _parent;

    #endregion

    #region Public properties

    public string Text
    {
        get { return _text; }
        set
        {
            if (value != _text)
            {
                _text = value;
                OnPropertyChanged("Text");
            }
        }
    }

    public bool IsChecked
    {
        get { return _isChecked; }
        set
        {
            if (value != _isChecked)
            {
                _isChecked = value;
                NotifyParent();
                OnPropertyChanged("IsChecked");
            }
        }
    }

    public ObservableCollection<TreeNodeViewModel> Nodes { get; private set; }

    public IEnumerable<TreeNodeViewModel> CheckedNodes
    {
        get
        {
            foreach (var node in Nodes)
            {
                if (node.IsChecked)
                    yield return node;
                foreach (var child in node.CheckedNodes)
                {
                    yield return child;
                }
            }
        }
    }

    public TreeNodeViewModel Parent
    {
        get { return _parent; }
        private set
        {
            if (value != _parent)
            {
                _parent = value;
                OnPropertyChanged("Parent");
            }
        }
    }

    #endregion
}

XAML

    <TreeView Grid.Row="0" ItemsSource="{Binding Nodes}">
        <TreeView.ItemTemplate>
            <HierarchicalDataTemplate ItemsSource="{Binding Nodes}">
                <StackPanel Orientation="Horizontal">
                    <CheckBox IsChecked="{Binding IsChecked}" />
                    <TextBlock Text="{Binding Text}" />
                </StackPanel>
            </HierarchicalDataTemplate>
        </TreeView.ItemTemplate>
    </TreeView>
    <ListBox Grid.Row="1" ItemsSource="{Binding CheckedNodes}">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding Text}" />
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

Код-за

        this.DataContext = new TreeNodeViewModel(
            null,
            new TreeNodeViewModel(
                "1",
                new TreeNodeViewModel(
                    "1.1",
                    new TreeNodeViewModel("1.1.1"),
                    new TreeNodeViewModel("1.1.2")),
                new TreeNodeViewModel("1.2")),
            new TreeNodeViewModel(
                "2",
                new TreeNodeViewModel("2.1"),
                new TreeNodeViewModel(
                    "2.2",
                    new TreeNodeViewModel("2.2.1"))));

Обратите внимание, что это довольно наивная реализация, которую можно легко улучшить ... Например, весь список проверенных узлов переоценивается каждый раз, когда узел проверяется / не проверяется, что может привести к плохой производительности для большого TreeView.

...