Custom control using dependency property in MVVM

A question for a beginner. After searching the internet a lot, I still cannot get a clean answer for this (standard) situation.

I have a UserControl_1 which will consist of one custom control and one WPF control. The custom control must be used in other WPF UserControls.

Ultimately, I would like to do this in the XAML of the main user control:

  XAML
      <i:UserControl_1  TargetDP = "{Binding SourceProperty, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" }" />

      

If SourceProperty is bound to the DataContext of the main user control and TargetDP is a dependency property in UserControl_1. Then UserControl_1 passes this TargetDP down / up through the controls it contains.

So where can I put the DependencyProperty for the UserControl?

It seems like it should go in code, but I'd really like to do it with MVVM.

UserControl_1 must have its own ViewModel separate from the Main User control, but information must be able to flow between the main view model and the custom control's view model (and vice versa) using the UserControl XAML bindings.

Thanks for any help or clarification on this. (Sorry if this looks like a duplicate, but none of the other articles indicate where to create a new custom control dependency property or how to do it.)

+3


source to share


1 answer


Here's how to do it (if I understand you correctly!). You have a custom control, name it MyControl

. CreateMyControlView

<UserControl x:Class="Project.Controls.MyControlView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d">
    <Grid HorizontalAlignment="Stretch"
            VerticalAlignment="Stretch">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <TextBlock Grid.Column="0" 
                   Text="{Binding LabelText}" 
                   VerticalAlignment="Center"
                   HorizontalAlignment="Right"
                   Margin="5,0"/>
        <ComboBox Grid.Row="1" 
                  ItemsSource="{Binding ComboBoxItems}"
                  SelectedItem="{Binding SelectedItem}"
                  HorizontalAlignment="Stretch"
                  Margin="0,0,5,0"/>
    </Grid>
</UserControl>

      

The view model will now be

public class MyControlViewModel
{
    // Add the public properties for LabelText, ComboBoxItems and SelectedItem
    // and any other logic you require.
}

      

Now for the bits you are confused. If I want to use this control in another view, name it BigView

, I can do



<Window x:Class="NameSpace.BigView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
        xmlns:Controls="clr-namespace:Project.Controls"> // Important reference to your control namespace.
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <Controls:MyControlView Grid.Row="0" Margin="0,5" 
                                DataContext="{Binding MyControlA}"/>
        <Controls:MyControlView Grid.Row="1" Margin="0,5" 
                                DataContext="{Binding MyControlB}"/>
    </Grid>
</Window>

      

Now in the view model BigViewModel

you will have two properties

public RangeSliderControlViewModel MyControlA { get; set; }
public RangeSliderControlViewModel MyControlB { get; set; }

      

So, you can access each control with MyControlA.LabelText = "Some Text"

et al. Note that the BigViewModel

MyControlA

/ MyControlB

does not need to be implemented INotifyPropertyChanged

, however the properties that you need to control must be updated and updated BigView

.

Hope this helps.

+3


source







All Articles