Nested Binding of UserControls
I am having trouble getting the following scenario to work (this code is not the actual code but the principals are the same. Basically I need to pass a value down from a MainPage down to a nested "reusable user control" that binds to it's own properties. I want to see the "This is it!" text on the screen but it's not being set in the SilverlightControl2 control (I suspect due to the setting of the DataContext) - but I how do I fix it?
MainPage.xaml
<Grid>
<ContentPresenter>
<ContentPresenter.Content>
<Local:SilverlightControl1 OneValue="This is it!"/>
</ContentPresenter.Content>
</ContentPresenter>
</Grid>
SilverlightControl1.xaml
<Grid>
<Local:SilverlightControl2 TwoValue="{Binding OneValue}"/>
</Grid>
SilverlightControl1.xaml.cs
public partial class SilverlightControl1 : UserControl
{
public string OneValue
{
get { return (string)GetValue(OneValueProperty); }
set { SetValue(OneValueProperty, value); }
}
public static readonly DependencyProperty OneValueProperty = DependencyProperty.Register(
"OneValue", typeof(string), typeof(SilverlightControl1), new PropertyMetadata(string.Empty));
public SilverlightControl1()
{
InitializeComponent();
this.DataContext = this;
}
}
SilverlightControl2.xaml
<Grid x:Name="LayoutRoot" Background="White">
<TextBlock Text="{Binding TwoValue}" Foreground="Blue" />
</Grid>
SilverlightControl2.xaml.cs
public partial class SilverlightControl2 : UserControl
{
public string TwoValue
{
get { return (string)GetValue(TwoValueProperty); }
set { SetValue(TwoValueProperty, value); }
}
public static readonly DependencyProperty TwoValueProperty = DependencyProperty.Register(
"TwoValue", typeof(string), typeof(SilverlightControl2), new PropertyMetadata(string.Empty));
public SilverlightContro开发者_如何学Gol2()
{
InitializeComponent();
this.DataContext = this;
}
}
As soon as you find yourself feeling the need to do this:-
this.DataContext = this;
know that you have probably got things wrong. Its probably the first thing I would expect to find on Silverlight specific "bad smell list".
In this case where you are specialising UserControl
a better approach is to do this:-
SilverlightControl1.xaml
<Grid>
<Local:SilverlightControl2 x:Name="MyControl2" />
</Grid>
SilverlightControl1.xaml.cs (I'm just showing the constructor the rest is as you have it)
public SilverlightControl1()
{
InitializeComponent();
MyControl2.SetBinding(SilverlightControl2.TwoValueProperty , new Binding("OneValue") { Source = this });
}
SilverlightControl2.xaml
<Grid x:Name="LayoutRoot" Background="White">
<TextBlock x:Name="MyTextBox" Foreground="Blue" />
</Grid>
SilverlightControl1.xaml.cs (I'm just showing the constructor the rest is as you have it)
public SilverlightControl2()
{
InitializeComponent();
MyTextBox.SetBinding(TextBox.TextProperty , new Binding("TwoValue") { Source = this });
}
Since in UserControls
you know the structure of the XAML and you can name the elements that you need access to in code, you can create the binding using a line of code instead.
This leaves the DataContext free to do what is designed for rather than be hi-jacked for a different purpose.
The alternative approach where instead of specialising UserControl
you create a templated control, in this case the binding can be expressed in XAML using something like:-
<TextBox Text="{TemplateBinding TwoValue}" />
Template binding only works in ControlTemplate
so you can't use it in a UserControl
.
精彩评论