The good news is that Silverlight 2.0 supports Data Binding. However, when I wanted to use it it did not work the way I expected it.
The Problem
Check out this Silverlight 2.0 XAML file:
xmlns="http://schemas.microsoft.com/client/2007"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300">
Here is the corresponding code behind:
using System.Windows;
using System.Windows.Controls;
using System.ComponentModel;
namespace SilverlightDataBinding
{
public partial class Page : UserControl
{
public Page()
{
DataContext = this;
SetValue(HelloTextProperty, "Silverlight is cool");
InitializeComponent();
ChangeHelloText.Click += new RoutedEventHandler(ChangeHelloText_Click);
}
void ChangeHelloText_Click(object sender, RoutedEventArgs e)
{
SetValue(HelloTextProperty, HelloText + " cool");
}
public string HelloText
{
get { return (string)GetValue(HelloTextProperty); }
set { SetValue(HelloTextProperty, value); }
}
public static readonly DependencyProperty HelloTextProperty =
DependencyProperty.Register("HelloText", typeof(string), typeof(Page), null);
}
}
If I run this application I can click on the button as often as I want. The content of the TextBlock never changes. However, in Visual Studio I can see that the value of the dependency property HelloText has changed! Seems to be a problem with refreshing the screen appropriately.
A Solution With CLR Objects
I wanted to know if the refresh problem also occurs with CLR objects that implement INotifyPropertyChanged. Therefore I changed the app shown above a little bit and I added a class.
Here is the XAML file after the changes:
xmlns="http://schemas.microsoft.com/client/2007"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300">
Here is the new class:
using System.ComponentModel;
namespace SilverlightDataBinding
{
public class TextContainer : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private string helloText;
public string HelloText
{
get
{
return helloText;
}
set
{
if (helloText != value)
{
helloText = value;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("HelloText"));
}
}
}
}
}
Last but not least the code behind file:
using System.Windows;
using System.Windows.Controls;
using System.ComponentModel;
namespace SilverlightDataBinding
{
public partial class Page : UserControl
{
private TextContainer textContainer;
public Page()
{
DataContext = this;
SetValue(HelloTextProperty, "Silverlight is cool");
textContainer = new TextContainer();
textContainer.HelloText = "Silverlight is cool";
InitializeComponent();
ChangeHelloText.Click += new RoutedEventHandler(ChangeHelloText_Click);
TextBlock_CLR.DataContext = textContainer;
}
void ChangeHelloText_Click(object sender, RoutedEventArgs e)
{
SetValue(HelloTextProperty, HelloText + " cool");
textContainer.HelloText += " cool";
}
public string HelloText
{
get { return (string)GetValue(HelloTextProperty); }
set { SetValue(HelloTextProperty, value); }
}
public static readonly DependencyProperty HelloTextProperty =
DependencyProperty.Register("HelloText", typeof(string), typeof(Page), null);
}
}
Believe it or not - the CLR class with INotifyPropertyChanged works!
Getting Dependency Properties to Work
Finally I found out that refreshing the screen works correctly with Dependency Properties if the object containing them also implements INotifyPropertyChanged:
using System.Windows;
using System.Windows.Controls;
using System.ComponentModel;
namespace SilverlightDataBinding
{
public partial class Page : UserControl, INotifyPropertyChanged
{
private TextContainer textContainer;
public event PropertyChangedEventHandler PropertyChanged;
public Page()
{
DataContext = this;
SetValue(HelloTextProperty, "Silverlight is cool");
textContainer = new TextContainer();
textContainer.HelloText = "Silverlight is cool";
InitializeComponent();
ChangeHelloText.Click += new RoutedEventHandler(ChangeHelloText_Click);
TextBlock_CLR.DataContext = textContainer;
}
void ChangeHelloText_Click(object sender, RoutedEventArgs e)
{
SetValue(HelloTextProperty, HelloText + " cool");
textContainer.HelloText += " cool";
}
public string HelloText
{
get { return (string)GetValue(HelloTextProperty); }
set { SetValue(HelloTextProperty, value); }
}
public static readonly DependencyProperty HelloTextProperty =
DependencyProperty.Register("HelloText", typeof(string), typeof(Page),
HelloTextChangedCallback);
public static void HelloTextChangedCallback( DependencyObject d, DependencyPropertyChangedEventArgs e )
{
var p = (Page)d;
if (p.PropertyChanged != null)
p.PropertyChanged(p, new PropertyChangedEventArgs("HelloText"));
}
}
}
I assume that this is a bug in Silverlight 2.0 Beta. Otherwise Silverlight would behave completely different than WPF.