Patrick
Patrick

Reputation: 419

UI not updating for bound element

My property updates just fine, but my user interface is not updated. What am i doing wrong?

I also tried setting the DataContext not in XAML, but in the code behind constructor, but that didn't work either.

ViewModel:

public class MainWindowViewModel : INotifyPropertyChanged
{
    public MainWindowViewModel()
    {
        TestCommand = new RelayCommand(UpdateTest);
    }

    #region INotifyPropertyChanged
    public event PropertyChangedEventHandler PropertyChanged;


    protected void NotifyPropertyChanged([CallerMemberName] string propertyName = null)
    {
        if (PropertyChanged != null)
            PropertyChanged(null, new PropertyChangedEventArgs(propertyName));
    }
    #endregion

    private string _test;
    public string Test 
    {
        get { return _test; }
        set 
        { 
            _test = value; 
            NotifyPropertyChanged(); 
        }
    }

    public ICommand TestCommand { get; set; }

    public void UpdateTest()
    {
        Test += "test ";
    }
}

View:

<Window x:Class="Test.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:Test"
    Title="MainWindow" Height="350" Width="525">
    <Window.DataContext>
        <local:MainWindowViewModel />
    </Window.DataContext>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <TextBox Grid.Row="0" Text="{Binding Test}"  />
        <Button  Grid.Row="1" Content="Test 2" Command="{Binding TestCommand}" />
    </Grid>
</Window>

Upvotes: 1

Views: 41

Answers (1)

Peter Duniho
Peter Duniho

Reputation: 70652

You are not implementing PropertyChanged correctly. The event model for .NET requires that the sender argument of the invoked delegates is set to the reference of the object actually raising the event. You set that value to null. Your code should use this instead:

protected void NotifyPropertyChanged([CallerMemberName] string propertyName = null)
{
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

Note that for thread safety, you should also not use the "check and raise" pattern on the event field itself. You should instead store the field in a local variable, check the local variable, and then raise the event from that variable if non-null. The above, which uses the ?. operator ("null conditional operator") effectively does this; the compiler generates the local variable implicitly for you and ensures that the reference won't change between the time you check it for null and the time you actually try to use it.

Upvotes: 3

Related Questions