We have an Item Details window that uses an instance of a ViewModel as the DataContext. We have a simple string property on the ViewModel called StatusMessage used to give feedback to the user. We've implement INotifyPropertyChanged on this view model and the StatusMessage property is configured to raise the event. The ViewModel has three other members that are classes (or collections) and on all of these work the bindings work like they should.
The problem is that the StatusMessage doesn't get updated in the GUI when it gets changed programmatically. We've debugged and found that the property really is changing and the on the Window code behind we subscribed to the property changed event and can see that the event really is firing.
Any control bound to StatusMessage will display whatever is set on the constructor, but it never updates after that.
I used two different controls, one a textbox with twoway binding and the other a label, both bound to StatusMessage. When I change the value using the TextBox, my label also changes. But any changes made inside the ViewModel never get propagated to the GUI.
There are no binding errors. We've even checked the HasBindingErrors property on the PropertyChanged event handler and it shows false and shows that our control is still bound to StatusMessage.
This problem only affects the base/root ViewModel class. All the members that are classes and have their own members and implement INotifyPropertyChanged work without any problems. We have full two way binding for those and they all work.
I've tried cleaning and rebuilding the project and it doesn't make any difference.
What can possibly cause a binding to fail without producing any error messages?
This is the actual code although I've had to trim out a lot in order to make it fit nicely here:
The XAML:
<Window x:Class="PZESpecsApp.SpecDetails"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"
xmlns:local="clr-namespace:SpecsApp"
Title="Spec Details" Height="600" Width="1000">
<Grid>
<TextBlock Text="{Binding spec.MakeAndModelNo}" FontSize="24" FontWeight="Bold" Margin="16,10,0,0" />
<TextBox Name="txtStatusMessage" Text="{Binding StatusMessage, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" FontSize="24" FontWeight="Bold" Foreground="Black" />
<Label Grid.Column="0" Content="{Binding Path=StatusMessage}" Foreground="White" />
</Grid>
</Window>
The window code:
public partial class SpecDetails : Window
{
private SpecDetailsViewModel model;
public SpecDetails(int id)
{
InitializeComponent();
model = new SpecDetailsViewModel(id);
model.PropertyChanged += ViewModel_PropertyChanged;
DataContext = model;
}
private void ViewModel_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
//this shows that the property actually changes as expected
Debug.Print("PropertyChanged=" + e.PropertyName);
}
}
The ViewModel Code:
public class SpecDetailsViewModel
{
public event PropertyChangedEventHandler PropertyChanged;
private Spec _spec;
public Spec spec
{
get { return _spec; }
set { _spec = value; PropertyChanged.Notify(() => this.spec); }
}
private string _statusMessage;
public string StatusMessage
{
get { return _statusMessage; }
set { _statusMessage = value; PropertyChanged.Notify(() => this.StatusMessage); }
}
public SpecDetailsViewModel(int id)
{
spec = AppData.SpecsList.FirstOrDefault(s => s.id == id);
StatusMessage = "Monkey See, Monkey Do!"; //this stays on the GUI
}
public void SaveSpec() {
//this doesn't have any affect on the GUI
this.StatusMessage = "Changes Saved";
}
}
ViewModel
! – dub stylee