Как добраться до SelectedItem во вложенном ListView - PullRequest
0 голосов
/ 03 мая 2020

Я борюсь с этими последними днями. Я нашел много ссылок, но ни одна из них мне не помогла. Я довольно новичок в WPF. Все, что мне нужно, это достичь свойства SelectedItem во вложенном ListView. Внешняя привязка ListView работает, конечно. То, что я попробовал после некоторого исследования и не работает, даже я не очень понимаю, почему это не работает:

<Window x:Class="ListViewRef.View.ListViewWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:vm="clr-namespace:ListViewRef.ViewModel"
        xmlns:local="clr-namespace:ListViewRef.View"
        mc:Ignorable="d"
        Title="Nested List Views" Height="450" Width="800">

    <Window.DataContext>
        <vm:MainVM/>
    </Window.DataContext>

    <StackPanel x:Name="Global">
        <TextBlock Text="{Binding MainTitle}"/>
        <ListView ItemsSource="{Binding Path=SourceCollection}"
                  SelectedItem="{Binding Path=OutterSelectedItem}"
                  >
            <ListView.ItemTemplate>
                <DataTemplate>
                    <StackPanel>
                        <TextBlock Text="{Binding Title}"/>
                        <TextBlock Text="Now second ListView:"/>
                        <ListView ItemsSource="{Binding Strings}"
                                  SelectedItem="{Binding Path=NestedSelectedItem,
                                RelativeSource={RelativeSource AncestorType=vm:MainVM},
                                Mode=TwoWay,
                                UpdateSourceTrigger=PropertyChanged}"
                                  ></ListView>
                    </StackPanel>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </StackPanel>
</Window>

И ViewModel:

using ListViewRef.Model;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;

namespace ListViewRef.ViewModel
{
    public class MainVM : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        private string mainTitle;

        public string MainTitle {
            get { return mainTitle; }
            set { mainTitle = value; OnPropertyChanged(nameof(MainTitle)); }
        }

        private string nestedSelectedItem;

        public string NestedSelectedItem {
            get { return nestedSelectedItem; }
            set 
            {
                nestedSelectedItem = value;
                MessageBox.Show("NestedSelectedItem: " + nestedSelectedItem);
                OnPropertyChanged(nameof(NestedSelectedItem)); 
            }
        }

        private string outterSelectedItem;

        public string OutterSelectedItem {
            get { return outterSelectedItem; }
            set 
            {
                outterSelectedItem = value;
                MessageBox.Show("OutterSelectedItem: " + OutterSelectedItem);
                OnPropertyChanged(nameof(OutterSelectedItem)); 
            }
        }

        public ObservableCollection<ClassWithObsList> SourceCollection { get; set; }

        public MainVM()
        {
            MainTitle = "Title of the Grid";

            SourceCollection = new ObservableCollection<ClassWithObsList> {
                new ClassWithObsList("First Title", new ObservableCollection<string> { "First", "Second"}),
                new ClassWithObsList("Second Title", new ObservableCollection<string> { "Third", "Fourth"}),
                new ClassWithObsList("Third Title", new ObservableCollection<string> { "Fifth", "Sixth"}),
            };
        }

        private void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

Класс модели:

using System;
using System.Collections.ObjectModel;
using System.ComponentModel;

namespace ListViewRef.Model
{
    public class ClassWithObsList : INotifyPropertyChanged
    {
        private string title;

        public string Title {
            get { return title; }
            set {
                title = value;
                OnPropertyChanged(nameof(Title));
            }
        }

        public ObservableCollection<string> Strings { get; set; }

        public event PropertyChangedEventHandler PropertyChanged;

        public ClassWithObsList(string title, ObservableCollection<string> strings)
        {
            Title = title ?? throw new ArgumentNullException(nameof(title));
            Strings = strings ?? throw new ArgumentNullException(nameof(strings));
        }

        private void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

1 Ответ

1 голос
/ 03 мая 2020

В

SelectedItem="{Binding Path=NestedSelectedItem,
               RelativeSource={RelativeSource AncestorType=vm:MainVM}, ...}

тип vm:MainVM не является типом предка внутреннего ListView, поскольку он не является частью визуального или логического дерева.

Тип AncestorType должен быть Элемент пользовательского интерфейса, например внешний ListView. Вы получите доступ к свойству с помощью вложенного свойства Path через его DataContext:

SelectedItem="{Binding Path=DataContext.NestedSelectedItem,
               RelativeSource={RelativeSource AncestorType=ListView}, ...}

В качестве примечания, поскольку вы не устанавливаете свойство View ListViews, вы также можете использовать более простой базовый класс ListBox вместо ListView:

<ListBox ItemsSource="{Binding Path=SourceCollection}"
         SelectedItem="{Binding Path=OutterSelectedItem}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel>
                <TextBlock Text="{Binding Title}"/>
                <TextBlock Text="Now second ListView:"/>
                <ListBox ItemsSource="{Binding Strings}"
                         SelectedItem="{Binding Path=DataContext.NestedSelectedItem,
                             RelativeSource={RelativeSource AncestorType=ListBox},
                             Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
            </StackPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...