I'm building a Windows Phone 8 app. I have a UserControl whose contents should get updated asynchronously. My model implements INotifyPropertyChanged. When I update a value in my model it propagates to a TextBox control as it should but not to the contents of my UserControl. What part of the puzzle am I missing or is it just not possible? Here's my reproduction scenario.
App page:
<phone:PhoneApplicationPage x:Class="BindingTest.MainPage">
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<Button Click="Button_Click" Content="Click" HorizontalAlignment="Left" Margin="147,32,0,0" VerticalAlignment="Top"/>
<TextBlock HorizontalAlignment="Left" Margin="69,219,0,0" TextWrapping="Wrap" Text="{Binding Bar}" VerticalAlignment="Top" Height="69" Width="270"/>
<app:MyControl x:Name="Snafu" HorizontalAlignment="Left" Margin="69,319,0,0" Title="{Binding Bar}" VerticalAlignment="Top" Width="289"/>
</Grid>
</phone:PhoneApplicationPage>
This is the code behind with the model class (Foo)
public partial class MainPage : PhoneApplicationPage
{
Foo foo;
// Constructor
public MainPage()
{
InitializeComponent();
foo = new Foo();
ContentPanel.DataContext = foo;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
foo.Bar = "Gnorf";
}
}
public class Foo : INotifyPropertyChanged
{
string bar;
public event PropertyChangedEventHandler PropertyChanged;
void OnPropertyChanged(string name)
{
if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(name));
}
public Foo()
{
Bar = "Welcome";
}
public string Bar
{
get
{
return bar;
}
set
{
bar = value;
OnPropertyChanged("Bar");
}
}
}
The UserControl xaml
<UserControl x:Class="BindingTest.MyControl">
<TextBox x:Name="LayoutRoot" Background="#FF9090C0"/>
</UserControl>
And the code behind for the UserControl
public partial class MyControl : UserControl
{
public MyControl()
{
InitializeComponent();
}
public static readonly DependencyProperty TitleProperty = DependencyProperty.Register("Title", typeof(string), typeof(MyControl), new PropertyMetadata("", OnTitleChanged));
static void OnTitleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
MyControl c = (MyControl)d;
c.Title = e.NewValue as String;
}
public string Title
{
get
{
return (string)GetValue(TitleProperty);
}
set
{
SetValue(TitleProperty, value);
LayoutRoot.Text = value;
}
}
}
When I run the example, the UserControl TextBox will contain welcome. When I click on the button the regular TextBox updates to Gnorf but the UserControl still displays Welcome.
I also discovered that if I only bind to the UserControl the PropertyChanged event handler is null when the call to set_DataContext returns. The DataBinding infrastructure seems to infer that the binding to my UserControl is a one-time binding instead of a regular one-way binding. Any ideas?
LayoutRoot.Text = value;
is meant to be run every time or only when you're calling the setter from code, but its a definite smell. – user1228