Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF Binding with INotifyPropertyChanged does not update

I appear to be having serious problems getting my WPF UI to update when I update when I update the property it is bound to. Here is my view model class definition:

namespace WpfModel
    {
        class AppModel : INotifyPropertyChanged
        {
            private int _count = 7;

        public int Count { get { return _count; } 
        set { _count = value;     OnPropertyChanged("Count"); } }

        public void Increment()
        {
            Count++;
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void OnPropertyChanged(string prop)
        {
            PropertyChangedEventHandler handler = this.PropertyChanged;

            if (handler != null)
            {
                var e = new PropertyChangedEventArgs("prop");
                handler(this, e);
            }
        }
    };
}

This is bound to my simple UI in the following XAML:

<Window x:Class="WpfModel.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:vm="clr-namespace:WpfModel"
        Title="WPF Data Model Demo" Height="128" Width="284" >

    <Window.DataContext>
        <vm:AppModel />
    </Window.DataContext>

    <Grid Height="Auto" Width="Auto">
        <Button Margin="0,0,12,12" Name="IncButton" Height="23" VerticalAlignment="Bottom" HorizontalAlignment="Right" Width="75" Click="IncButton_Click" Content="Increment" />
        <Label Content="Count Variable:" Height="28" HorizontalAlignment="Left" Margin="12,12,0,0" Name="label1" VerticalAlignment="Top" />
        <Label Height="28" Margin="116,12,0,0" Name="CountLabel" VerticalAlignment="Top" HorizontalAlignment="Left" Width="40" Content="{Binding Path=Count}" />
    </Grid>
</Window>

The application is defined like follows:

namespace WpfModel
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private AppModel _model = new AppModel();

        public MainWindow()
        {
            InitializeComponent();

            //_model = new AppModel();
        }

        private void IncButton_Click(object sender, RoutedEventArgs e)
        {
        }
    }
}

When the app starts up, everything is peachy, the label even initially displays whatever value is in the Count property of the model. Calling increment updates the model properly, and directly incrementing the Count property as shown in the code also works just fine.

The problem here, is that the PropertyChanged event handler never seems to get added to. I can step through the code in the debugger and see the value in the property updating, and I can see the call to OnPropertyChanged even, but the PropertyChanged handler itself is always null.

Is there a problem with my binding maybe?

I am using MSVC 2010 Express.

like image 826
Chris D. Avatar asked Jun 18 '10 21:06

Chris D.


2 Answers

The issue is that the WpfModel you have as an instance variable, _model, is not the same instance that's being used as the Window's DataContext. Thus, it is not bound to by anything, and its PropertyChanged will always be null.

Change your XAML for setting the datacontext to this:

<Window.DataContext>
            <vm:AppModel x:Name="_model" />
</Window.DataContext>

Get rid of the instance variable declared in the code behind, and fix the OnPropertyChanged implementation (use the parameter instead of the literal string "prop"), and it works.

like image 83
ArildF Avatar answered Oct 25 '22 01:10

ArildF


this line:

var e = new PropertyChangedEventArgs("prop");

should be:

var e = new PropertyChangedEventArgs(prop);

You are passing the string "prop" so the bound values listening for "Count" will not be triggered.

**EDIT ** Based on your other comments (Answer?) I thought I had better update this with a fix - you could use the answer already given of course but I dont want to copy someone else :).

Add this to your click handler:

((AppModel)this.DataContext).Count += 1;
like image 30
Leom Burke Avatar answered Oct 25 '22 00:10

Leom Burke