Search code examples
c#wpfviewmodelinotifypropertychanged

WPF component content not updating after view model change


I have the following view model:

public class ViewModel : ObservableObject
{
    public string Watermark { get; set; } = "Loading...";
}

where ObservableObject is from Microsoft.Toolkit.Mvvm.ComponentModel which implements INotifyPropertyChanged and INotifyPropertyChanging.

I have the following XAML:

<xctk:WatermarkTextBox>
    <xctk:WatermarkTextBox.WatermarkTemplate>
        <DataTemplate>
            <ContentControl Content="{Binding DataContext.Watermark, RelativeSource={RelativeSource AncestorType=Window}}"></ContentControl>
        </DataTemplate>
    </xctk:WatermarkTextBox.WatermarkTemplate>
</xctk:WatermarkTextBox>

And lastly the following C# code:

private async void Window_Loaded(object sender, RoutedEventArgs e)
{
    Dispatcher.Invoke(() =>
    {
        // Assigning property of textbox directly with .Watermark = "" does not work

        // Updating view model property doesn't work either
        Model.Watermark = "Done";
    });
}

When the window loaded method gets called however, the watermark of the watermark textbox does not update to reflect its supposed new value, "Done".

It might be a lack of general WPF understanding but if anyone could give a pointer as to why this might fail I would greatly appreciate it.

Thanks!


Solution

  • You aren't using ObservableObject properly. It's not magic (unlike some solutions that use frameworks such as Fody), so you still have to do the work yourself to propagate changes. Note the example in the documentation.

    public class User : ObservableObject
    {
        private string name;
    
        public string Name
        {
            get => name;
            set => SetProperty(ref name, value);
        }
    }
    

    So you'll have to follow that pattern:

    public class ViewModel : ObservableObject
    {
        private string watermark;
    
        public ViewModel() 
        {
            Watermark = "Loading...";
        }
    
        public string Watermark
        {
            get => watermark;
            set => SetProperty(ref watermark, value);
        }
    }