首页 > 解决方案 > 将文本绑定到数组对象中的嵌套成员

问题描述

我挑战自己在 WPF 中制作我的应用程序,我以前从未尝试过 :)

也许这很明显,但我不明白我的错误在哪里。

我的RecipePage正确显示部分<TextBlock Text="{Binding Name}">但没有<TextBlock Text="{Binding Path=Details[0].PieceName}"> (或 1)

我没有错误,只是没有。

是由Recipe.AddDetails()哪个没有发送任何PropertyChanged事件引起的吗?

预先感谢您的帮助 :)

食谱页面.xaml

...
<Grid>
    <Button HorizontalAlignment="Left" Width="112" Height="29" VerticalAlignment="Top" Content="PRECEDENT" Margin="10"/>
    <StackPanel>
        <TextBlock Text="{Binding Name}" Style="{StaticResource h1}"></TextBlock>
        <StackPanel Orientation="Horizontal">
            <StackPanel>
                <TextBlock Text="{Binding Path=Details[0].PieceName}" Style="{StaticResource h2}"></TextBlock>
            ...
            </StackPanel>
            <StackPanel>
                <TextBlock Text="{Binding Path=Details[1].PieceName}" Style="{StaticResource h2}"></TextBlock>
            ...
            </StackPanel>
        </StackPanel>
    </StackPanel>
</Grid>
...

RecipePage.xaml.cs

public partial class RecipePage : Page
{

    public RecipePage(Recipe recipe)
    {
        InitializeComponent();
        DataContext = recipe;
    }
}

页面创建:

    private void OnBourguignonClick(object sender, RoutedEventArgs e)
    {
        var recipe = new Recipe("BOURGUIGNON ou SAUTE", 190, "images/recipes/rotideboeuf.jpg");
        recipe.AddDetails(new RecipeDetails("paleron", 6, 31));
        recipe.AddDetails(new RecipeDetails("sauté maigre", 190, 221));
        ((MainWindow)Application.Current.MainWindow)?.NavigationFrame.NavigationService.Navigate(new RecipePage(recipe));
    }

食谱.cs

public class Recipe : INotifyPropertyChanged
{
    public string Name { get; set; }

    public int MeatWeightPerPers { get; set; }

    public string ImagePath { get; set; }

    public RecipeDetails[] Details = new RecipeDetails[]{};

    public event PropertyChangedEventHandler PropertyChanged;

    public Recipe(string name, int meatWeight, string image)
    {
        Name = name;
        MeatWeightPerPers = meatWeight;
        ImagePath = image;
    }

    public void AddDetails(RecipeDetails details)
    {
        Details.Append(details);
    }
}

RecipeDetails.cs

public class RecipeDetails : INotifyPropertyChanged
{
    public string PieceName { get; set; }
    public int PieceWeightPerCow { get; set; }
    public int NbPersPerCow { get; set; }

    public event PropertyChangedEventHandler PropertyChanged;

    public RecipeDetails(string pieceName, int pieceWeightPerCow, int nbPersPerCow)
    {
        PieceName = pieceName;
        PieceWeightPerCow= pieceWeightPerCow;
        NbPersPerCow = nbPersPerCow;
    }
}

FodyWeavers.xml(已安装)

<?xml version="1.0" encoding="utf-8"?>
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
  <PropertyChanged />
</Weavers>

标签: c#wpfxamldata-bindingnested

解决方案


主要问题是添加元素Details不会引发CollectionChanged事件。此事件由ObservableCollection更改时自动引发,因此您需要使用它而不是数组:

public class Recipe : INotifyPropertyChanged
{
    public string Name { get; set; }

    public int MeatWeightPerPers { get; set; }

    public string ImagePath { get; set; }

    // Instead of array, use ObservableCollection
    public ObservableCollection<RecipeDetails> Details { get; set; }

    public event PropertyChangedEventHandler PropertyChanged;

    public Recipe(string name, int meatWeight, string image)
    {
        Name = name;
        MeatWeightPerPers = meatWeight;
        ImagePath = image;

        // Initialize Details collection
        Details = new ObservableCollection<RecipeDetails>();
    }

    public void AddDetails(RecipeDetails details)
    {
        Details.Add(details);
    }
}

由于Details是某种列表,您可能希望使用 anItemsControl而不是单独TextBlock的 s 来显示它:

...
<Grid>
    <Button HorizontalAlignment="Left" Width="112" Height="29" VerticalAlignment="Top" Content="PRECEDENT" Margin="10"/>
    <StackPanel>
        <TextBlock Text="{Binding Name}" Style="{StaticResource h1}"></TextBlock>
        <StackPanel Orientation="Horizontal">
            <ItemsControl ItemsSource="{Binding Details}">
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <StackPanel>
                            <TextBlock Text="{Binding PieceName}" Style="{StaticResource h2}" />
                            ...
                        </StackPanel>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
        </StackPanel>
    </StackPanel>
</Grid>
...

推荐阅读