Search code examples
c#dependency-propertieswinui-3

SetBinding to custom dependency properties is not updated after the initial update


// MainWinodw.xaml.cs

namespace TestApp
{
    [ObservableObject]
    public sealed partial class MainWindow : Window
    {
        [ObservableProperty]
        private Brush _myBrush = new SolidColorBrush(Colors.Beige);

        public MainWindow()
        {
            InitializeComponent();

            Task.Run(async () =>
            {
                int count = 0;

                while (true)
                {
                    await Task.Delay(1000);

                    var color = (++count % 3) switch
                    {
                        0 => Colors.Red,
                        1 => Colors.Green,
                        2 => Colors.Blue,
                        _ => throw new System.NotImplementedException(),
                    };

                    DispatcherQueue.TryEnqueue(() => MyBrush = new SolidColorBrush(color));
                }
            });
        }
    }

    public class CustomButton : Button
    {
        public Brush Background2
        {
            get => (Brush)GetValue(Background2Property);
            set => SetValue(Background2Property, value);
        }
        public static readonly DependencyProperty Background2Property =
            DependencyProperty.Register(nameof(Background2), typeof(Brush), typeof(CustomButton), new(null));

        public CustomButton()
        {
            Loaded += (_, _) =>
            {
                ClearValue(BackgroundProperty);
                SetBinding(BackgroundProperty, new Binding
                {
                    Source = Background2,
                    Mode = BindingMode.OneWay,
                });
            };
        }
    }
}
<!--MainWindow.xaml-->

<Window x:Class="TestApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:TestApp">
    <Grid>
        <local:CustomButton Background2="{x:Bind MyBrush, Mode=OneWay}"
                            Content="Button" />
    </Grid>
</Window>

If you execute the above code, the button will no longer be updated after the first update to beige.

I checked that set accessor of Background2 is called every second.

Why is the Background of the CustomButton not being updated?

What I'm really trying to do is add DependencyProperties to Window, but it's not possible because Window doesn't inherit DependencyObject. Therefore, I intend to achieve my purpose by injecting a class that inherits the DependencyObject into Window's subclass.


Solution

  • The problem is your Background2 => Background binding is wrong. You must declare it like this instead:

    SetBinding(BackgroundProperty, new Binding
    {
        Source = this,
        Path = new PropertyPath(nameof(Background2)),
        Mode = BindingMode.OneWay,
    });