Saturday, September 18, 2010

Binding when DataContext with Explicit Interface Implementation (INotifyPropertyChanged)

In this article, we will discuss how to support change notification using INotifyPropertyChanged when your DataContext explicitly implements some interface. You might want to bind some of the explicitly implemented property to your View.

Lets consider this interface. This is defining a contract of having a string property, named Name. Both get and set are part of the interface contract.

public interface IWindow1ViewModel
{
string Name { get; set; }
}

Now we implement this interface in class Window1ViewModel. This class explicitly implements this interface. The interesting thing is that this class should also support change notification of its properties, so it implements INotifyPropertyChanged. Look at setter of Name property. You can see that in order to support change notification with INotifyPropertyChanged, we don't need to generate notification with the name of interface and just the name of property should work.

public class Window1ViewModel : INotifyPropertyChanged, IWindow1ViewModel
{
#region IWindow1ViewModel Members

string _name;
string IWindow1ViewModel.Name
{
get
{
return _name;
}
set
{
_name = value;
onPropertyChanged("Name");
}
}
#endregion

#region INotifyPropertyChanged Members

public event PropertyChangedEventHandler PropertyChanged;

private void onPropertyChanged(string fieldName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(fieldName));
}
}

#endregion
}

Now we need to bind this to the view. Lets create a view Window1. Here we are specifying Window1ViewModel as data context. The interesting thing is how we should be binding this to the view. As you know that we can not access explicitly implemented properties using object reference, we must be using interface name somehow, in order to specify the property name. When we specify like this, WPF runtime knows that this property is explicitly implemented by data context using the interface specified.

<Window x:Class="INotifyPropertyChanged_ExplicitInterface.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:INotifyPropertyChanged_ExplicitInterface"
DataContext="{DynamicResource ViewModel}"
Title="Window1" Height="300" Width="300">
<Window.Resources>
<local:Window1ViewModel x:Key="ViewModel" />
</Window.Resources>
<StackPanel>
<TextBox Width="100" Height="100">
<TextBox.Text>
<Binding Path="(local:IWindow1ViewModel.Name)" />
</TextBox.Text>
</TextBox>
</StackPanel>
</Window>

No comments: