Search code examples
c#xamlwinui-3winui.net-9.0

Background color binding doesnt get the right value after items source is updated (WinUI 3, .NET 9)


I'm trying to update the background color of some custom controls I created, based on the values from an observable collection bound to the XAML through a data template, but the bindings get wrong values after the collection changes. The other properties get updated correctly. See the end of the post for new important info

I tried changing the property name and applying the template every time a property changed, but it didn't work.

CustomControls(project)/Themes/Generic.xaml:

<Style TargetType="local:CustomTableCard">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="local:CustomTableCard">
                <Grid Height="300" Width="300" BorderThickness="4" Background="{Binding BackgroundColorProp, RelativeSource={RelativeSource TemplatedParent},
                                Mode=OneWay, FallbackValue='Black', TargetNullValue='Blue'}">

CustomControls/CustomTableCard.cs

public class CustomTableCard : Control
{
   public static readonly DependencyProperty BackgroundColorProperty = 
   DependencyProperty.Register(
      nameof(BackgroundColorProperty),
      typeof(string),
      typeof(CustomTableCard),
      new PropertyMetadata(null));

   public string BackgroundColorProp
   {
      get => (string)GetValue(BackgroundColorProperty);
      set => SetValue(BackgroundColorProperty, value);
   }

   public CustomTableCard()
   {
      this.DefaultStyleKey = typeof(CustomTableCard);
   }

   protected override void OnApplyTemplate()
   {
      base.OnApplyTemplate();
      [...]
   }

View(Packaged project)/CustomTablePage.xaml:

<Page.Resources>
    <DataTemplate x:Key="CustomTableItemTemplateNew" x:DataType="Data:CustomTableCardData">
        <ItemContainer>
            <customControls:CustomTableCard TableName="{x:Bind TableNameData, Mode=OneWay}"
                                            TextColor="{x:Bind TextColorData, Mode=OneWay}"
                                            [...]
                                            BackgroundColorProp="{x:Bind BackgroundColorData}"
                                            TableDeletionRequested="CustomTableItem_TableDeletionRequested"
                                            />
        </ItemContainer>
    </DataTemplate>
</Page.Resources>

[...]

<ItemsView x:Name="itemsViewTables" HorizontalAlignment="Stretch"
            ItemTemplate="{StaticResource CustomTableItemTemplateNew}"
            ItemsSource="{x:Bind Data:CustomTableCardDataRepository.customTableItemsCollection, Mode=OneWay}"

View/CustomTablePage.xaml.cs:

public void loadTables()
{
    CustomTableCardDataRepository.FillCustomTablesCollection((int)userId);

    itemsViewTables.ItemsSource = CustomTableCardDataRepository.customTableItemsCollection;
}

Even though the data in customTableItemsCollection is correct before and after it's assigned to items source, the binding for the grid background gets an incorrect value.

Page just loaded with the data from loadTables()

enter image description here

New tables added without reloading the whole page. Just called loadTables() and filled the customTableItemsCollection with the correct data:

enter image description here

It feels like the colors somehow get mixed between the controls. Then if I simply switch pages and go back to that one, everything gets displayed correctly again:

enter image description here

Sometimes, all buttons get green backgrounds:

enter image description here

But When I debug, I can see the first button's property is being set to white in CustomControls/CustomTableCard.cs:

enter image description here

The first button is bound to the correct property but it's not the right color

enter image description here

Data in itemsSource:

enter image description here

I also got this after restarting the app and removing the other button(card). I have no idea where it's getting this color from if there aren't any other buttons. It couldn't be a data mix, I suppose? Unless it's getting the previous data somehow.

enter image description here

New info: I experimented changing the default button color and it changed the bugged color as well enter image description here

enter image description here

I debbuged the constructor code but it never reached the line that sets the property to pink when there was only the first button(image above), instead it set the property to white, which is the correct data.

Data(project)/CustomTableCard.cs

enter image description here

With that, I think it's fairly accurate to say that it's getting previous data from other buttons that were removed. The binding is probably bugged. I don't know how to approach this issue though...


Solution

  • The DependencyProperty is not correct.

    Try the following:

    public static readonly DependencyProperty BackgroundColorPropProperty =
        DependencyProperty.Register(
            nameof(BackgroundColorProp),
            typeof(string),
            typeof(CustomTableCard),
            new PropertyMetadata(null));
    
    public string BackgroundColorProp
    {
        get => (string)GetValue(BackgroundColorPropProperty);
        set => SetValue(BackgroundColorPropProperty, value);
    }