如何在嵌套的ListView中到达SelectedItem [英] How to reach SelectedItem in nested ListView

查看:48
本文介绍了如何在嵌套的ListView中到达SelectedItem的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

最近几天我在努力.我找到了很多链接,但没有一个真正对我有帮助.我是WPF的初学者.我需要做的就是在嵌套ListView中到达SelectedItem属性.当然,外部ListView绑定有效.经过一些研究后,我尝试了一下但没有用,甚至我真的不明白为什么它不起作用:

I'm wrestling with these last few days. I found lots of links, but none of them really helped me. I'm quite a beginner in WPF. All I need is to reach SelectedItem property in nested ListView. Outter ListView binding works, of course. What I tried after some research and doesn't work, even I don't really understand why it dosnt work:

<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:

And 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));
        }
    }
}

推荐答案

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

vm:MainVM 类型不是内部ListView的祖先类型,因为它不是可视树或逻辑树的一部分.

the type vm:MainVM is not an ancestor type of the inner ListView, because it not part of a visual or logical tree.

AncestorType必须是一个UI元素,例如外部ListView.您将通过嵌套的属性Path通过其DataContext访问该属性:

The AncestorType must be a UI element, e.g. the outer ListView. You would access the property by a nested property Path via its DataContext:

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


请注意,由于您没有设置ListViews的 View 属性,因此也可以使用更简单的基类ListBox代替ListView:


As a note, since you are not setting the View property of the ListViews, you could as well use the simpler base class ListBox instead of 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>

这篇关于如何在嵌套的ListView中到达SelectedItem的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆