Привязка текста к вложенному элементу в объекте в массиве - PullRequest
0 голосов
/ 12 марта 2019

Я поставил перед собой задачу подать заявку в WPF, никогда раньше не пробовал :)

Может быть, это очевидно, но я не понимаю, где моя ошибка.

Мой RecipePage правильно отображает деталь <TextBlock Text="{Binding Name}">, но ничего для <TextBlock Text="{Binding Path=Details[0].PieceName}"> (или 1)

У меня нет ошибок, просто ничего.

Это вызвано Recipe.AddDetails(), который не отправляет никакого события PropertyChanged?

Заранее благодарим за помощь:)

RecipePage.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));
    }

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>

1 Ответ

1 голос
/ 12 марта 2019

Основная проблема в том, что добавление элемента в 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 - это какой-то список, вы, вероятно, захотите отобразить его, используя ItemsControl, а не отдельные 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>
...
...