Aly El-Haddad February 2016

How to bind a DependencyProperty of a UserControl to a property in it's ViewModel in MVVM?

The question is not about how to get the stuff working, it already does; it's about some strange behavior I'm experiencing, and I need to understand it. I have a ResourceDictionary that contains some styles, one of them got TargetType="{x:Type UserControl}" and x:Key="UCStyle"; that one is applied on multiple UserControls in the project. Some of these UserControls got string State property in their ViewModel to be used to apply Visual States (through an external class, and an attached property, bound to the ViewModel in XAML). Till this point everything was perfect, then, I tried to add DependencyProperty State to the UserControl, and simply bind it to the state property in the ViewModel, my attempt was:

<UserControl.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <!--ResourceDictionary Source="..."/-->
        </ResourceDictionary.MergedDictionaries>
        <Style x:Key="MyStyle" TargetType="{x:Type local:MyUserControl}" BasedOn="{StaticResource UCStyle}">
            <Setter Property="State" Value="{Binding State, Mode=TwoWay}"/>
        </Style>
    </ResourceDictionary>
</UserControl.Resources>
<UserControl.Style>
    <DynamicResourceExtension ResourceKey="MyStyle" />
</UserControl.Style>

This worked perfectly at the runtime, but in the design-time, it always underline these lines 'MyUserControl' TargetType doesn't match type of element 'UserControl'.

And shows an error says:

'MyUserControl' TargetType doesn't match type of element 'UserControl'.

And doesn't apply neither UCStyle nor MyStyle

Answers


Will February 2016

The wpf designer is nefarious for showing bogus errors at design time. You can't do much but ignore them.

Visual states are a concern of the UI, and therefore should be contained within the UI. MVVM does not mean no codebehind. Use your codebehind for UI tasks, and put your business logic in your view models.

Your question suggests you're creating custom view models to hold view logic for your user controls. Seriously, don't do that. That'll get you in trouble down the road. It interferes with how databinding is designed to work.

There is no "best practice" for binding user control elements to properties defined on its surface. It depends. Using a style to do this seems odd, however. You can simply give the root of the UserControl an x:Name="root" and then use ElementName=root in your binding.

An example of binding within a UserControl to a property defined on the UserControl (taken from an old prototype)...

Here's a UserControl designed to add or delete a list of stuff.

  • DependencyProperties defined on the UserControl
  • Bindings within the UserControl that bind to these properties

I don't guarantee this works, but it will illustrate how it's done:

public partial class ItemsEditor : UserControl
{
    #region Items
    public static readonly DependencyProperty ItemsProperty =
        DependencyProperty.Register(
            "Items",
            typeof(IEnumerable<Item>),
            typeof(ItemsEditor),
            new UIPropertyMetadata(null));
    public IEnumerable<Item> Items
    {
        get { return (IEnumerable<Item>)GetValue(ItemsProperty); }
        set { SetValue(ItemsProperty, value); }
    }
    #endregion  
    #region AddItem
    public static readonly DependencyProperty AddItemProperty =
        DependencyProperty.Register(
            "AddItem",
            typ 

Post Status

Asked in February 2016
Viewed 3,911 times
Voted 9
Answered 1 times

Search




Leave an answer