Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / WPF, Silverlight Новый топик    Ответить
 Binding Selected TreeNode  [new]
fritz321
Member

Откуда:
Сообщений: 16
Здравствуйте!
весь вечер голову ломаю - не могу придмумать как забиндить выделенный сегмент TreeView переменной Mvvm

весь TreeView тут
<TreeView ItemsSource="{Binding Subunits}">
                    <!-- Шаблон подразделения -->
                    <TreeView.ItemTemplate>
                        <HierarchicalDataTemplate ItemsSource="{Binding Positions}">
                            <TextBlock Text="{Binding SubunitName}"/>
                            <!-- Шаблон должности -->
                            <HierarchicalDataTemplate.ItemTemplate>
                                <HierarchicalDataTemplate ItemsSource="{Binding Employees}" DataType="{x:Type local:Employee}">
                                    <TextBlock Text="{Binding PositionName}"/>
                                    <!-- Шаблон сотрудника -->
                                    <HierarchicalDataTemplate.ItemTemplate>
                                        <DataTemplate>
                                            <StackPanel Orientation="Horizontal">                                                
                                                <TextBlock Text="{Binding FirstName}" Margin="0,0,5,0" MouseDown="qwe"/>
                                                <TextBlock Text="{Binding FirstName}" Margin="0,0,5,0"/>
                                                <TextBlock Text="{Binding Patronymic}" Margin="0,0,5,0"/>
                                            </StackPanel>
                                        </DataTemplate>
                                    </HierarchicalDataTemplate.ItemTemplate>
                                    
                                </HierarchicalDataTemplate>
                            </HierarchicalDataTemplate.ItemTemplate>
                        </HierarchicalDataTemplate>
                    </TreeView.ItemTemplate>
                </TreeView>


плюс сложность в том что каждый дочерний узел, экземпляр другого класса, чем родительский, но я думаю не проблема.
Просто не могу найти решение о том как на клик забиндить переменную HierarchicalDataTemplate
27 дек 14, 22:33    [17062515]     Ответить | Цитировать Сообщить модератору
 Re: Binding Selected TreeNode  [new]
Roman Mejtes
Member

Откуда: г. Пермь
Сообщений: 4036
а) для начала в модели представления нужно создать базовый класс для элемента иерархического списка.
он может наследоваться от базового класса модели представления или как то еще, дело ваше.
Лично я создаю примерно такой класс:

вот пример такого класса взятый из проекта:

    public sealed class LoadingTreeItem : BaseTreeItem
    {
        public override string DisplayName
        {
            get { return "Loading..."; }
        }
    }

    public abstract class BaseTreeItem : INotifyPropertyChanged
    {
        public static ObservableCollection<BaseTreeItem> LoadingItems { set; get; }

        static BaseTreeItem()
        {
            LoadingItems = new ObservableCollection<BaseTreeItem> {new LoadingTreeItem()};
        }

        private bool _isExpanded;
        private ObservableCollection<BaseTreeItem> _children;
        public virtual string DisplayName { set; get; }

        public ObservableCollection<BaseTreeItem> Children
        {
            set
            {
                if (Equals(value, _children)) return;
                _children = value;
                OnPropertyChanged();
            }
            get
            {
                ObservableCollection<BaseTreeItem> result;
                if (IsLoaded && HasItems) return _children;
                if (!IsLoaded && HasItems) return LoadingItems;
                return null;
            }
        }

        public BaseTreeItem Parent { set; get; }

        public bool HasItems
        {
            set
            {
                if (value.Equals(_hasItems)) return;
                _hasItems = value;
                OnPropertyChanged();
            }
            get { return _hasItems; }
        }

        public virtual bool IsLoaded { set; get; }
        public virtual bool IsLoading { set; get; }
        public Func<BaseTreeItem, IEnumerable<BaseTreeItem>> LoadChildrenFunc { set; get; }
        public bool IsSelected { set; get; }

        public bool IsExpanded
        {
            set
            {
                if (!CanExpand) return;
                if (value.Equals(_isExpanded)) return;
                _isExpanded = value;
                if (_isExpanded) LoadChildren();
                OnPropertyChanged();
            }
            get { return _isExpanded; }
        }

        private Task<IEnumerable<BaseTreeItem>> GetChildren()
        {
            var factory = new TaskFactory();
            return factory.StartNew(() => LoadChildrenFunc(this));
        }

        public bool CanExpand { get { return LoadChildrenFunc != null; } }

        private bool _hasItems;

        private async void LoadChildren()
        {
            if (!CanExpand) return;

            IsLoading = true;
            var result = await GetChildren();
            IsLoading = false;
            IsLoaded = true;
            Children = new ObservableCollection<BaseTreeItem>(result);
        }

        public event PropertyChangedEventHandler PropertyChanged;

        [NotifyPropertyChangedInvocator]
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }

у данного базового класса есть свойство IsSelected, он примет значение True. В качество метода для загрузки элементов используется делегат, который вызывается асинхронно и загружает элементы дерева. Это достаточно топорный пример, я просто дома и что нашел, то и скинул.
Само свойство определяющее выделение элемента находится в элемента TreeViewItem, в котором размещается шаблон данных. TreeView Автоматически создает данный элемент и размещает его в своей панели, а внутри размещает ContentPresenter для шаблона данный. (всё это можно увидеть в визуальном дереве WPF приложения с помощью сторонних утилит или внутр. инструментами). TreeViewItem имеет зависимое свойство IsSelected и именно к нему нужно биндить свойства в модели преставления.
Вот пример:
        
        <Style TargetType="{x:Type TreeViewItem}">
            <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}"/>
            <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}"/>
        </Style>

обязательно указываем режим связывания TwoWay, так как по умолчанию они OneWay.
Вот собственно и всё. Теперь выделенные элементы дерева будут имеет свойство IsSelected, нужно их только найти и использовать. ) Но вообще, в WPF это вообще не нужно в большинстве случаев. Так как при использовании маршрутизирующих и обычных команд, ты можешь передать в виде параметра выделенный элемент дерева и не париться с его поиском вообще. Этот вариант как по мне будет более правильный.
28 дек 14, 11:54    [17063283]     Ответить | Цитировать Сообщить модератору
 Re: Binding Selected TreeNode  [new]
fritz321
Member

Откуда:
Сообщений: 16
автор
ты можешь передать в виде параметра выделенный элемент дерева и не париться с его поиском вообще. Этот вариант как по мне будет более правильный.

можно об этом поподробней?
28 дек 14, 12:36    [17063369]     Ответить | Цитировать Сообщить модератору
 Re: Binding Selected TreeNode  [new]
fritz321
Member

Откуда:
Сообщений: 16
Roman Mejtes,

нашел хорошее решение вот тут
но оно помогло только от части.

Там описывается расширенный класс TreeView которому добавляется свойство SelectedItem
Вопрос остался в создании такого класса для HierarchicalDataTemplate потому что у него такого свойства нет
28 дек 14, 14:04    [17063588]     Ответить | Цитировать Сообщить модератору
 Re: Binding Selected TreeNode  [new]
Roman Mejtes
Member

Откуда: г. Пермь
Сообщений: 4036
fritz321,

напиши на скайп и я вышлю тебе пример проекта roman_meites.
AttachedProperty для такой простой задачи вообще бесмысленен.
Всё это можно сделать прямо в модели представления.
способ через AttachedProperty основан на рекурсивном поиске по визуальному дереву (скорее всего). Тоже вариант, но имхо слишком громоздкий.
28 дек 14, 18:36    [17064246]     Ответить | Цитировать Сообщить модератору
 Re: Binding Selected TreeNode  [new]
fritz321
Member

Откуда:
Сообщений: 16
Roman Mejtes,

почта моя kolenchits86@gmail.com
28 дек 14, 21:03    [17064749]     Ответить | Цитировать Сообщить модератору
Все форумы / WPF, Silverlight Ответить