Wednesday, August 29, 2012

PropertyChangedEventHandler always null in silverlight binding

PropertyChangedEventHandler always null in silverlight binding

I've been trying to resolve this issue for some time. I'm trying to bind a TextBlock's text to a string property using the INotifyPropertyChanged interface. For some reason the PropertyChangedEventHandler is always null when the value of the property is changed thus the target never gets updated... Any suggestions? Code below:

XAML code:

<UserControl x:Class="MoleDashboard.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"  xmlns:basics="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls" xmlns:datacontrols="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data" xmlns:primitives="clr-namespace:System.Windows.Controls.Primitives;assembly=System.Windows.Controls.Data" xmlns:prop="clr-namespace:MoleDashboard"   <UserControl.Resources> <prop:YearScreen x:Key="YearScreenProps"/> </UserControl.Resource>  <TextBlock Margin="10 5" x:Name="DataGridLabel" Visibility="Visible" Text="{Binding   YearProperty, Source={StaticResource YearScreenProps}, Mode=OneWay}"/> 

Bound property code:

public class YearScreen : INotifyPropertyChanged {     private string metricProperty;      private string yearProperty;      public event PropertyChangedEventHandler PropertyChanged;      public YearScreen()     {     }      public string YearProperty     {         get { return yearProperty; }         set { yearProperty = value; this.OnPropertyChanged("YearProperty"); }     }      public string MetricProperty     {         get { return metricProperty; }         set { metricProperty = value; this.OnPropertyChanged("MetricProperty"); }     }       public void OnPropertyChanged(string property)     {         if (PropertyChanged != null)         {             PropertyChanged(this, new PropertyChangedEventArgs(property));         }     }   } 

Answers & Comments...

Answer: 1

This is based on the comments provided and not just the question above.

Basically the problem is that you are creating updating a second instance of your ViewModel (called a YearScreen in your code) and updating that.

A YearScreen is already being created and bound to your Xaml, by the inclusion of:

<UserControl.Resources>     <prop:YearScreen x:Key="YearScreenProps"/> </UserControl.Resource> 

You are then creating a second ViewScreen elsewhere in code (via new ViewScreen()) and updating that, however there is no connection between the 2 ViewScreen instances, so nothing will update in the Xaml page.

One Possible (quick) solution:

Create your YearScreen as a singleton. That is add a static accessor of type YearScreen in the class and set it from the constructor.

    public class YearScreen : INotifyPropertyChanged     {         private static YearScreen _This;          public static YearScreen This { get { return _This; } }  [snip]          public YearScreen()         {             _This = this;         } 

The you can access the "single" instance of your YearScreen from elsewhere using the static singleton accessor e.g.:

YearScreen.This.YearProperty = DateTime.Now.ToString(): 

There are better patterns for sharing ViewModels than singletons, but that will get you going.

The pattern you started with is ViewFirst creation (the view creates the ViewModel). ModelFirst does the opposite, but is bad as the model knows how it is displayed. Using a controller object to create the View and ViewModel and connect them is a better alternative, but that is then getting quite complicated. Using injection of single instance objects is a better option, but involves a whole load of new concepts. Lookup Silverlight Prism after you solve your current problems.

by : HiTech Magichttp://stackoverflow.com/users/201078

Answer: 2

Instead of creating the ViewModel in the resources you should set it into the DataContext of the view from external code.

If you really want to put it in the Resources like that you can get it out of the resources in the code behind Loaded method or in the constructor after the initializecomponent call. Like so:

private YearScreen model;  public MainPage() {     this.Loaded += MainPage_Loaded;     this.InitializeComponent(); }  void MainPage_Loaded(object sender, EventArgs e) {     this.model = (YearScreen)this.Resources["YearScreenProps"]; } 

Maybe expose it as a property so you can then access it externally. But personally I'd rather create the model externally than pass it into the View instead. Put it into the DataContext.

by : justin.m.chasehttp://stackoverflow.com/users/12958




No comments:

Post a Comment

Send us your comment related to the topic mentioned on the blog