Установить isselected свойства TreeViewItem в TreeView WPF, MVVM

я новичок в WPF mvvm, я создал древовидную структуру и хочу установить значение isSelected для определенного элемента древовидной структуры в этом дереве (например, элемент с «19-ASDFDSSD»), но я не знаю, как это сделать. Вы можете помочь мне? Любая помощь будет оценена.

деревокод wpf

ВакансииDTOClass

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
87
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

TreeView.SelectedItem доступен только для чтения, поэтому значение не может быть передано из ViewModel.

Я справился с этим с помощью класса Behavior.

1. Создайте базовый класс для данных элемента TreeView, который включает свойства IsSelected и IsExpanded.

public class perTreeViewItemViewModelBase : perViewModelBase
{
    private bool _isSelected;

    public bool IsSelected
    {
        get => _isSelected;
        set => Set(nameof(IsSelected), ref _isSelected, value);
    }

    private bool _isExpanded;

    public bool IsExpanded
    {
        get => _isSelected;
        set => Set(nameof(IsExpanded), ref _isExpanded, value);
    }


    ...
}

2. Создайте вспомогательный класс для элементов управления TreeView для реализации поведения с прикрепленным свойством BoundSelectedItem.

public class perTreeViewHelper : Behavior<TreeView>
{
    public object BoundSelectedItem
    {
        get => GetValue(BoundSelectedItemProperty);
        set => SetValue(BoundSelectedItemProperty, value);
    }

    public static readonly DependencyProperty BoundSelectedItemProperty =
        DependencyProperty.Register("BoundSelectedItem",
            typeof(object),
            typeof(perTreeViewHelper),
            new FrameworkPropertyMetadata(null,
                FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
                OnBoundSelectedItemChanged));

    private static void OnBoundSelectedItemChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
    {
        if (args.NewValue is perTreeViewItemViewModelBase item)
        {
            item.IsSelected = true;
        }
    }

    protected override void OnAttached()
    {
        base.OnAttached();
        AssociatedObject.SelectedItemChanged += OnTreeViewSelectedItemChanged;
    }

    protected override void OnDetaching()
    {
        AssociatedObject.SelectedItemChanged -= OnTreeViewSelectedItemChanged;
        base.OnDetaching();
    }

    private void OnTreeViewSelectedItemChanged(object obj, RoutedPropertyChangedEventArgs<object> args)
    {
        BoundSelectedItem = args.NewValue;
    }
}

3. Создайте стили для TreeViewItem и TreeView, чтобы привязать свойство IsSelected экземпляра perTreeViewItemViewModelBase к соответствующему свойству TreeViewItem.

<Style x:Key = "perTreeViewItemContainerStyle" TargetType = "{x:Type TreeViewItem}">
    <!--  Link the properties of perTreeViewItemViewModelBase to the corresponding ones on the TreeViewItem  -->
    <Setter Property = "IsExpanded" Value = "{Binding IsExpanded, Mode=TwoWay}" />
    <Setter Property = "IsSelected" Value = "{Binding IsSelected, Mode=TwoWay}" />

    ...

</Style>

<Style TargetType = "{x:Type TreeView}">
    <Setter Property = "ItemContainerStyle" Value = "{StaticResource perTreeViewItemContainerStyle}" />
</Style>

4. В представлении используйте класс поведения для привязки присоединенного свойства BoundSelectedItem к соответствующему свойству в ViewModel.

<TreeView ItemsSource = "{Binding ...}">

    <i:Interaction.Behaviors>
        <vhelp:perTreeViewHelper BoundSelectedItem = "{Binding SelectedItem}" />
    </i:Interaction.Behaviors>

Для получения более подробной информации о моем понимании того, как обрабатывать элементы управления TreeView в контексте MVVM (включая флажки для выбора элемента и отложенную загрузку данных элемента), ознакомьтесь с моим сообщением в блоге.

Большое спасибо, ваше решение немного сложно для меня, но я, гость, знаю, как оно работает. Чтобы упростить ваше решение, я добавил логический атрибут «IsSelected» в свой класс JobsDTO и добавил <Setter Property = «IsSelected» Value = «{Binding IsSelected»> в свой wpf. Итак, если я хочу установить выбранное задание в моем представлении в виде дерева , я изменю его на истину.

Kouhny 24.11.2022 13:42

Это должно сработать. Поместите первые две строки кода в метод. Treeview — это имя вашего дерева. Элемент из основного источника элементов (ваши данные)

var treeviewitem = GetTreeViewItem(treeview, item);   
treeviewitem.IsSelected = true;     

public TreeViewItem GetTreeViewItem(ItemsControl container, object item)
{
    if (container != null)
    {
        if (container.DataContext == item)
            return container as TreeViewItem;

        container.ApplyTemplate();
        ItemsPresenter itemsPresenter = (ItemsPresenter)container.Template.FindName("ItemsHost", container);
        if (itemsPresenter != null)
        {
            itemsPresenter.ApplyTemplate();
        }
        else
        {
            itemsPresenter = FindVisualChild<ItemsPresenter>(container);
            if (itemsPresenter == null)
            {
                container.UpdateLayout();
                itemsPresenter = FindVisualChild<ItemsPresenter>(container);
            }
        }
        Panel itemsHostPanel = (Panel)VisualTreeHelper.GetChild(itemsPresenter, 0);
        UIElementCollection children = itemsHostPanel.Children;
        foreach (TreeViewItem treeviewitem in children)
        {
            TreeViewItem resulttreeviewitem = SelectItem(treeviewitem, item);
            if (resulttreeviewitem != null)
            {
                resulttreeviewitem.BringIntoView();
                return resulttreeviewitem;
            }
        }
    }
    return null;
}

private static T FindVisualChild<T>(Visual visual) where T : Visual
{
    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(visual); i++)
    {
        Visual child = (Visual)VisualTreeHelper.GetChild(visual, i);
        if (child != null)
        {
            T correctlyTyped = child as T;
            if (correctlyTyped != null)
                return correctlyTyped;

            T descendent = FindVisualChild<T>(child);
            if (descendent != null)
                return descendent;
        }
    }
    return null;
} 

Другие вопросы по теме