我正在学习如何构建更复杂的数据结构,以及如何在 WPF 中绑定它们。鉴于下面的数据结构,我无法弄清楚如何调用 OnPropertyChanged() 以便列表框正确更新。 ListBox 正在寻找什么 PropertyName?
主窗口.xaml
<Window x:Class="GUITest2.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:GUITest2"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<StackPanel>
<ListBox ItemsSource="{Binding container}" DisplayMemberPath="Name" Height="100"/>
<Button Command="{Binding ButtonCommand}" HorizontalAlignment="Left" Margin="10,10,10,10" VerticalAlignment="Bottom" Height="30" Width="80"/>
</StackPanel>
</Grid>
</Window>
MainWindow.xaml.cs
using System;
using System.Collections.Generic;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using System.Windows;
using System.Collections;
namespace GUITest2;
public partial class MainWindow : Window {
public People container { get; set; } = new();
public MainWindow() {
InitializeComponent();
DataContext = this;
}
[RelayCommand]
public void Button() {
container.Add("Harry");
}
}
public class People : ObservableObject, IEnumerable<People.Person> {
readonly List<Person> _dataList = new();
public People() {
_dataList.Add(new Person() { Name = "Bob" });
_dataList.Add(new Person() { Name = "Jeff" });
}
public void Add(string Name) {
OnPropertyChanging("Name");
_dataList.Add(new Person() { Name = Name });
OnPropertyChanged("Name");
}
public IEnumerator<Person> GetEnumerator() {
return _dataList.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator() {
return ((IEnumerable)_dataList).GetEnumerator();
}
public class Person {
public string Name { get; internal set; } = "";
}
}
使您的
People
类派生自 ObservableCollection
而不是 ObservableObject
。它配备了使 ListBox
与 People
实例同步所需的一切。
public class People : ObservableCollection<People.Person> {
public People() {
this.Add(new Person() { Name = "Bob" });
this.Add(new Person() { Name = "Jeff" });
}
public class Person {
public string Name { get; internal set; } = "";
}
}
或者,如果您使用 NET Desktop 8,那就更好了:
public class People : ObservableCollection<People.Person> {
public People()
: base([
new Person() { Name = "Bob" },
new Person() { Name = "Jeff" },
])
{
}
public class Person {
public string Name { get; internal set; } = "";
}
}
此外,有什么理由将
Person
类定义为 People
类的一部分?
此外,关于
container
属性。
由于这是一个(公共)属性,请遵循 Pascal-casing 所说的命名约定,因此调整为
Container
(大写字母)。
这里不清楚你的意图:它是一个仅限初始化的属性,或者更确切地说可以随着时间的推移而改变?
第一种情况,按如下方式更改其签名,以防止误导性设置,该设置不会投射到 XAML 端:
public People Container { get; init; } = new();
或:
public People Container { get; } = new();
否则,只需实现 PropertyChanged 模式,或者更好的是,作为 DependencyProperty 实现。但是,如果您是新手,这有点复杂。