使用 DisplayMemberPath 时 WPF 中的 ListBox 绑定到什么 PropertyName?

问题描述 投票:0回答:1

我正在学习如何构建更复杂的数据结构,以及如何在 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; } = "";
    }
}
c# wpf data-binding
1个回答
0
投票

使您的

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
属性。

  1. 由于这是一个(公共)属性,请遵循 Pascal-casing 所说的命名约定,因此调整为

    Container
    (大写字母)。

  2. 这里不清楚你的意图:它是一个仅限初始化的属性,或者更确切地说可以随着时间的推移而改变?

第一种情况,按如下方式更改其签名,以防止误导性设置,该设置不会投射到 XAML 端:

public People Container { get; init; } = new();

或:

public People Container { get; } = new();

否则,只需实现 PropertyChanged 模式,或者更好的是,作为 DependencyProperty 实现。但是,如果您是新手,这有点复杂。

© www.soinside.com 2019 - 2024. All rights reserved.