Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UserControl's DataContext

I'm creating a UserControl I want to use something like this:

<controls:ColorWithText Color="Red" Text="Red color" /> 

So far, I've implemented similar controls like this:

<UserControl x:Class="Namespace.ColorWithText" Name="ThisControl">     <StackPanel Orientation="Horizontal" >         <Border Width="15" Height="15" Background="{Binding Color, ElementName=ThisControl}" />         <TextBlock Text="{Binding Text, ElementName=ThisControl}" />     </StackPanel> </UserControl> 

where Color and Text are dependency properties of the control defined in code. This works, but specifying ElementName every time seems unnecessary.

Another option that works is using

<UserControl x:Class=… DataContext="{Binding ElementName=ThisControl}" Name="ThisControl"> 

and not specifying ElementNames, but that doesn't seem like a clean solution to me either.

I have two questions:

  1. Why doesn't <UserControl DataContext="{RelativeSource Self}"> work?
  2. What is the best way to do something like this?
like image 206
svick Avatar asked Feb 22 '11 11:02

svick


People also ask

What is a DataContext in WPF?

The DataContext property is the default source of your bindings, unless you specifically declare another source, like we did in the previous chapter with the ElementName property. It's defined on the FrameworkElement class, which most UI controls, including the WPF Window, inherits from.

What is DataContext?

Data context is the network of connections among data points. Those connections may be created as metadata or simply identified and correlated. Contextual metadata adds value, essentially making it possible to receive information from data. A single data point on its own is useless.

Should a user control have a VIewModel?

Your UserControls should NOT have ViewModels designed specifically for them. This is, in fact, a code smell. It doesn't break your application immediately, but it will cause you pain as you work with it. A UserControl is simply an easy way to create a Control using composition.


2 Answers

For first one, try :

<UserControl DataContext="{Binding RelativeSource={RelativeSource Self}}"> 

And for second question, I think using ElementName or AncestorBinding is best way to bind to UserControl's properties.

like image 79
decyclone Avatar answered Sep 21 '22 20:09

decyclone


Why can't you use <UserControl DataContext="{RelativeSource Self}">?

This is how you would use the control

<Grid DataContext="{StaticResource ViewModel}">     <!-- Here we'd expect this control to be bound to -->     <!-- ColorToUse on our ViewModel resource          -->     <controls:ColorWithText Color="{Binding ColorToUse}" /> </Grid> 

Now because we've hardcoded our data-context in the control it will instead attempt to lookup ColorToUse property on the ColorWithText object not your ViewModel, which will obviously fail.

This is why you can't set the DataContext on the user control. Thanks to Brandur for making me understand that.

What is the best way to do something like this?

Instead you should set the DataContext in the first child UI element in your control.

In your case you want

<StackPanel    DataContext="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}"   Orientation="Horizontal" > 

Now you have a DataContext which refers to your control so you can access any properties of that control using relative bindings.

like image 23
pdross Avatar answered Sep 23 '22 20:09

pdross