views:

75

answers:

3

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.

+3  A: 

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;
Leom Burke
You made the same error in your "fix" - gotta leave off the quotes here, too ;)
Reed Copsey
ahem, you might want to check your code
zendar
Haha - Copy and paste - thanks guys
Leom Burke
Thanks for the update, once I read the post by ArildF below I looked into making sure my _model instance variable was actually the one being used by the form, and of course it wasn't. :-)<code>_model = this.DataContext as AppModel</code>Fixed everything for me, once I took care of the "prop" typo (whoops!).Thanks for the helpful responses everyone!
Chris D.
A: 

Get round handlers being null by setting them to an empty delegate:

public event PropertyChangedEventHandler PropertyChanged = delegate { };

No more null checks.

Lunivore
+1  A: 

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.

ArildF