如何根据数据结构集合更新一系列用户控件?

How do I update a series of user controls based on a collection of data structures?

我有一个用户控件 BookViewControl,它只包含一个 StackPanel,我还有一个名为 BookInfoControl 的控件,它在一个 WrapPanel 中包含两个 TextBlock。在 BookViewControl 的代码隐藏中,我有一个数据结构的 Observable 集合(书籍)(名为 BookInfo,其中包含两个字符串属性,一个用于作者,另一个用于书名)。

我想要的是以这样一种方式设置它,当我向可观察集合(书籍)添加或删除一个项目时,BookViewControl 中的堆栈面板将通过添加或删除 BookInfoControl 的实例来更新(其中BookInfoControl 的 txtName 绑定到相应的 BookInfo 的 BookName 属性,而 BookInfoControl 的 txtAuthor 将绑定到相同的 BookInfos AuthorName 属性)。

因此我的问题有两个方面: 1) 如何基于集合动态创建/删除 UserControls。 2) 如何将这些控件添加到另一个 Controls StackPanel。

我知道我可以将 BookInfo 的实例及其属性绑定到 BookInfoControls TextBlocks 的实例(在 XAMl 中使用 Text={Binding SomeDataMember.Path} 或在后面的代码中使用 instanceName.SetBinding(新绑定{ Source = SomeDataMember, Path = new PropertyPath("Path") }); )。但是,这样做不会导致我的 Books 集合的新成员创建 BookInfoControl 的新实例,也不会解决将其添加到 StackPanel 的问题。

我还考虑过加入一些杂物来管理 BookInfoControls 的辅助集合,然后手动同步它,但这看起来太混乱了,我相信 WPF 应该有一种更简单、更简洁的方法。

BookViewControl.xaml

<UserControl x:Class="GenericNamespace.BookViewControl "
             ... Default Generated Namespace Definitions ...
    >
    <Grid>
        <StackPanel x:Name="pnlCollectionOfBookInfos" />
    </Grid>
</UserControl>

BookInfoControl.xaml

<UserControl x:Class="GenericNamespace.BookInfoControl "
             ... Default Generated Namespace Definitions ...
    >
    <Grid>
        <WrapPanel>
            <TextBlock x:Name="txtName"/>
            <TextBlock x:Name="txtAuthor"/>
        </WrapPanel>
    </Grid>
</UserControl>

BookInfo.cs

public class BookInfo
{
    public string AuthorName { get; set; } = "";
    public string BookName { get; set; } = "";
}

BookViewControl.cs

    public partial class BookViewControl: UserControl
    {
        public ObservableCollection<BookInfo> Books { get; set; } = new ObservableCollection<BookInfo>();

        public BookViewControl()
        {
            this.DataContext = this;
            InitializeComponent();
        }
    }

最后,修改 Books 应该会导致在 BookViewControl 的 StackPanel 中显示或删除 BookInfoControl,其中 BookInfoControls TextBlocks 的文本属性反映了 BookInfo 中公开的属性。

编辑:以下 link 是我根据我在这里得到的答案找到的,并且更深入地了解了这个主题,希望它对下一个提出这个问题的人有用:https://docs.microsoft.com/en-us/dotnet/framework/wpf/data/data-templating-overview

欢迎来到 SO!

每当您想使用数据绑定在 WPF 中呈现项目集合时,您必须使用 ItemsControl 或其派生控件之一:

<ItemsControl ItemsSource="{Binding Books}" />

如果你这样做,你会看到每本书都显示为一个字符串,你可以通过为你的书类型声明一个 DataTemplate 来改变它:

<UserControl.Resources>

    <DataTemplate DataType="{x:Type local:BookInfo}">
        <local:BookInfoControl />
    </DataTemplate>

</UserControl.Resources>