views:

34

answers:

2

I wanted to do a quick user control for my app, but to keep things in a MVVM style I thought I'd set the DataContext of the XAML to the code behind in my UserControl.

i.e.

DataContext="{Binding RelativeSource={RelativeSource Self}}"

This allows me to bind the XAML to properties in my code behind.

Everything went well until I came to bind the Visibility of an instance of the control to a Visibility property on a ViewModel.

<Controls:RoundProgress Visibility="{Binding ProgressVisibility}" Width="100" Height="100"></Controls:RoundProgress>

The Visibility no longer works - if I remove my tinkerings with the DataContext from the User Control - the visibility works!

Can someone set me right please? Thanks

+2  A: 

Don't set the DataContext of the UserControl itself from the internal XAML. By doing that you override the inherited DataContext and make your Binding look for a ProgressVisibility property on the UC instead of your ViewModel. Instead set the DataContext on an element inside the UC:

<UserControl x:Class...>
  <Grid DataContext="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}}">
    ...
  </Grid>
</UserControl>
John Bowen
Thanks, that works perfectly.
Andy Clarke
+1  A: 

DataContext is inherited. If you have changed the DataContext of your control so that it no longer references the viewmodel and points to itself instead then child controls will no longer be able to access properties on the viewmodel.

If you have a property in your code-behind which points to the viewmodel you can do this:

<Controls:RoundProgress Visibility="{Binding ViewModel.ProgressVisibility}" ...

Or you can leave the datacontext as is (pointing to the viewmodel) and add the relative source to any bindings where you want the data to come from the codebehind instead - for example:

<Button Text="{Binding ButtonText, Source={RelativeSource Mode=FindAncestor, AncestorType={x:Type MyUserControl}}}"/>
Martin Harris