0

I challenged myself to make my application in WPF, I never tried before :)

Maybe it's obvious but I don't understand where is my mistake.

My RecipePage display correctly the part <TextBlock Text="{Binding Name}"> but nothing for <TextBlock Text="{Binding Path=Details[0].PieceName}"> (or 1)

I have no error, just nothing.

Is it caused by Recipe.AddDetails() which no send any PropertyChanged event ?

Thank you in advance for your help :)

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;
    }
}

Page creation:

    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 (installed)

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

1 Answers1

1

The main problem is that adding an element to Details doesn't raise the CollectionChanged event. This event is automatically raised by the ObservableCollection when it's changed, so you'll want to use that instead of an array:

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

Since Details is some kind of list, you'll probably want to display it using an ItemsControl rather than using individual TextBlocks:

...
<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>
...
redcurry
  • 2,381
  • 2
  • 24
  • 38
  • Do you know why my details `items` are stacked vertically instead of horizontally while my `ItemsControl` parent panel is an `` ? – hexaJer Mar 13 '19 at 01:15
  • 1
    Your `StackPanel` only orients its contents, not the contents of the `ItemsPanel`. But there's a solution: see https://stackoverflow.com/a/1052512/1383366 – redcurry Mar 13 '19 at 01:26
  • Oh ok ! I thought `ItemsControl` generate only items in the parent container. Thank you – hexaJer Mar 13 '19 at 13:35