Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/337.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在嵌套的ListView中访问SelectedItem_C#_Wpf_Listview_Mvvm - Fatal编程技术网

C# 如何在嵌套的ListView中访问SelectedItem

C# 如何在嵌套的ListView中访问SelectedItem,c#,wpf,listview,mvvm,C#,Wpf,Listview,Mvvm,这几天我一直在挣扎。我找到了很多链接,但没有一个对我有帮助。我是WPF的初学者。 我只需要在嵌套的ListView中访问SelectedItem属性。 当然,Outter ListView绑定是有效的。 我做了一些研究后尝试了什么,但没有成功,即使我真的不明白为什么它没有成功: <Window x:Class="ListViewRef.View.ListViewWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xa

这几天我一直在挣扎。我找到了很多链接,但没有一个对我有帮助。我是WPF的初学者。 我只需要在嵌套的ListView中访问SelectedItem属性。 当然,Outter 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>

和视图模型:

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));
        }
    }
}
使用ListViewRef.Model;
使用System.Collections.ObjectModel;
使用系统组件模型;
使用System.Windows;
名称空间ListViewRef.ViewModel
{
公共类MainVM:INotifyPropertyChanged
{
公共事件属性更改事件处理程序属性更改;
私有字符串主标题;
公共字符串主标题{
获取{return mainttitle;}
设置{maintTitle=value;OnPropertyChanged(nameof(maintTitle));}
}
私有字符串nestedSelectedItem;
公共字符串NestedSelectedItem{
获取{return nestedSelectedItem;}
设置
{
nestedSelectedItem=值;
MessageBox.Show(“NestedSelectedItem:+NestedSelectedItem”);
OnPropertyChanged(名称(NestedSelectedItem));
}
}
私有字符串outterSelectedItem;
公共字符串OutterSelectedItem{
获取{return outterSelectedItem;}
设置
{
outterSelectedItem=值;
MessageBox.Show(“OutterSelectedItem:+OutterSelectedItem”);
OnPropertyChanged(名称为(OutterSelectedItem));
}
}
公共ObservableCollection源集合{get;set;}
公共MainVM()
{
mainttitle=“网格的标题”;
SourceCollection=新的ObservableCollection{
新类WithObsList(“第一个标题”,新的ObservableCollection{“第一”,“第二”}),
新类WithObsList(“第二个标题”,新的ObservableCollection{“第三个”,“第四个”}),
新类WithObsList(“第三个标题”,新的ObservableCollection{“第五个”,“第六个”}),
};
}
私有void OnPropertyChanged(字符串propertyName)
{
if(PropertyChanged!=null)
PropertyChanged(这是新的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));
        }
    }
}
使用系统;
使用System.Collections.ObjectModel;
使用系统组件模型;
名称空间ListViewRef.Model
{
带有obslist的公共类:INotifyPropertyChanged
{
私有字符串标题;
公共字符串标题{
获取{返回标题;}
设置{
标题=价值;
财产变更(名称(所有权));
}
}
公共ObservableCollection字符串{get;set;}
公共事件属性更改事件处理程序属性更改;
公共类WithObsList(字符串标题、ObservableCollection字符串)
{
Title=Title??抛出新的ArgumentNullException(nameof(Title));
Strings=Strings??抛出新ArgumentNullException(nameof(Strings));
}
私有void OnPropertyChanged(字符串propertyName)
{
if(PropertyChanged!=null)
PropertyChanged(这是新的PropertyChangedEventArgs(propertyName));
}
}
}
中的

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

AncestorType必须是UI元素,例如外部ListView。您可以通过嵌套属性路径通过其DataContext访问该属性:

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

请注意,由于您没有设置ListView的
视图
属性,因此您也可以使用更简单的基类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>


非常感谢您的帮助和解释,这解决了问题。我现在理解对了吗,RelativeSource设置了我要绑定到的UI元素的DataContext?不完全是“what DataContext”,而是绑定的源对象。源由绑定的source、RelativeSource或ElementName属性设置,如果未设置这些属性,则由目标元素的DataContext设置。DataContext属性的值由子元素从其父元素继承,这就是为什么ListView的DataContext是窗口的DataContext。我在推导中看到了错误。非常感谢你,克莱门斯。这很有帮助。
<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>