WPF 列表视图选定项未使用数据模板中的扩展器进行更新



我正在使用 C# 和 MVVM 创建一个 WPF 应用程序,我在SelectedItemListView 时遇到了一些问题。

在人为的示例中,场景:我有一个包含Person对象列表的PersonViewModel。每个 Person 对象都有自己的Address对象列表。我的目标是将所有 Person 对象加载到ListView中。此外,ListView DataTemplate应包括显示每个人可用地址的扩展器。

问题是:这一切实际上都足够体面。唯一的问题是,如果用户为 person 对象选择扩展器,它实际上不会更改ListViewSelectedItem属性(绑定到视图模型中的 SelectedPerson 对象(。

我相对有信心代码在其他方面工作,因为如果我单击 ListView 行(在包含的扩展器的边界之外(,SelectedPerson属性就会更新。当扩展器单击到 SelectedPerson 属性时,是否有任何方法可以以某种方式绑定?(我也对其他UI想法持开放态度,这些想法将以更干净,更易于实现的方式传达我的信息(。

Person.cs

using System.Collections.Generic;
namespace ListViewExpanderTest
{
public class Person
{
public Person()
{
Addresses = new List<Address>();
}
public string Name { get; set; }
public List<Address> Addresses { get; set; }
}
}

Address.cs

namespace ListViewExpanderTest
{
public class Address
{
public int HouseNumber { get; set; }
public string StreetName { get; set; }
public string City { get; set; }
}
}

PersonViewModel.cs

using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace ListViewExpanderTest
{
public class PersonViewModel : INotifyPropertyChanged
{
private Person _selectedPerson;
private Address _selectedAddress;
public List<Person> People { get; set; }
public Person SelectedPerson
{
get
{
return _selectedPerson;
}
set
{
_selectedPerson = value;
OnPropertyChanged();
}
}
public Address SelectedAddress
{
get
{
return _selectedAddress;
}
set
{
_selectedAddress = value;
OnPropertyChanged();
}
}
public PersonViewModel()
{
People = new List<Person>
{
new Person
{
Name = "Person 1",
Addresses = new List<Address>
{
new Address {HouseNumber = 1, StreetName = "Fake St", City = "Fake City" },
new Address {HouseNumber = 2, StreetName = "Super Fake St", City = "Super Fake City" }
}
},
new Person
{
Name = "Person 2",
Addresses = new List<Address>
{
new Address {HouseNumber = 10, StreetName = "Fake St", City = "Fake City" },
new Address {HouseNumber = 20, StreetName = "Super Fake St", City = "Super Fake City" }
}
}
};
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}

MainWindow.xaml

<Window x:Class="ListViewExpanderTest.MainWindow"
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:local="clr-namespace:ListViewExpanderTest"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<local:PersonViewModel />
</Window.DataContext>
<Grid>
<ListView ItemsSource="{Binding People, Mode=TwoWay}"
SelectedItem="{Binding SelectedPerson}">
<ListView.ItemTemplate>
<DataTemplate>
<Expander >
<Expander.Header>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}" />
</StackPanel>
</Expander.Header>
<Expander.Content>
<ListView ItemsSource="{Binding Addresses, Mode=TwoWay}"
SelectedItem="{Binding SelectedAddress}">
<ListView.View>
<GridView>
<GridViewColumn Width="50" Header="Number" DisplayMemberBinding="{Binding HouseNumber}" />
<GridViewColumn Width="100" Header="Street" DisplayMemberBinding="{Binding StreetName}" />
<GridViewColumn Width="100" Header="City" DisplayMemberBinding="{Binding City}" />
</GridView>
</ListView.View>
</ListView>
</Expander.Content>
</Expander>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</Window>

由于您的视图模型包含单个SelectedPerson属性,因此在数据模板中包含扩展器对我来说没有意义。如果您可以更改 UI,下面的示例对我来说似乎更有意义。显然,您可以将地址"面板"放置在您喜欢的任何位置。

另外,您是否尝试过从子列表视图中选择地址?绑定是否有效?

<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<ListView ItemsSource="{Binding People, Mode=TwoWay}"    
SelectedItem="{Binding SelectedPerson}"
DisplayMemberPath="Name">           
</ListView>
<ListView Grid.Column="1" 
ItemsSource="{Binding SelectedPerson.Addresses, Mode=TwoWay}" 
SelectedItem="{Binding SelectedAddress}">
<ListView.View>
<GridView>
<GridViewColumn Width="50" Header="Number" DisplayMemberBinding="{Binding HouseNumber}" />
<GridViewColumn Width="100" Header="Street" DisplayMemberBinding="{Binding StreetName}" />
<GridViewColumn Width="100" Header="City" DisplayMemberBinding="{Binding City}" />
</GridView>
</ListView.View>
</ListView>
</Grid>

最新更新