none
Binding an object to a dependency property in a UserControl (MVVM) RRS feed

  • Question

  • Hello. Basically, I'm trying to bind an object from my MainWindowViewModel to a custom UserControl, pass that object to data in the UserControl's ViewModel, and then display the data.

    <Window.DataContext>
        <viewmodels:MainWindowViewModel /
    </Window.DataContext>
    
    <controls:MyUserControl MyObjectProperty="{Binding Path=MyObject}" />

    And then the UserControl is basically like this...

    <UserControl.DataContext>
        <viewmodels:MyUserControlViewModel />
    </UserControl.DataContext>
    
    <TextBlock Text="{Binding Path=MyObject.SomeValue}" />

    The UserControl has its own ViewModel as well. And I notice when I don't set its DataContext I can bind my object but because I'm no longer using its ViewModel I can't pass the value to it for the backend logic.

    Am I maybe missing a RelativeSource reference of some kind that would allow me to bind to the UserControl, pass it to the ViewModel, and everything work?

    Thanks!

    Friday, November 22, 2019 4:32 PM

Answers

  • Hello. Basically, I'm trying to bind an object from my MainWindowViewModel to a custom UserControl, pass that object to data in the UserControl's ViewModel, and then display the data.

    <Window.DataContext>
        <viewmodels:MainWindowViewModel /
    </Window.DataContext>
    
    <controls:MyUserControl MyObjectProperty="{Binding Path=MyObject}" />

    And then the UserControl is basically like this...

    <UserControl.DataContext>
        <viewmodels:MyUserControlViewModel />
    </UserControl.DataContext>
    
    <TextBlock Text="{Binding Path=MyObject.SomeValue}" />

    The UserControl has its own ViewModel as well. And I notice when I don't set its DataContext I can bind my object but because I'm no longer using its ViewModel I can't pass the value to it for the backend logic.

    Am I maybe missing a RelativeSource reference of some kind that would allow me to bind to the UserControl, pass it to the ViewModel, and everything work?

    Thanks!

    Hi    T Gregory, 

    C# Version for your reference:

    UserControl:

      <UserControl.DataContext>
            <local:MyUserControlViewModel />
        </UserControl.DataContext>
        <Grid>
            <TextBox HorizontalAlignment="Left" Height="43" Margin="121,114,0,0" TextWrapping="Wrap" DataContext="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}" Text="{Binding ValueBC, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"  VerticalAlignment="Top" Width="350"/>
        </Grid>
    
    
        /// <summary>
        /// Interaction logic for UserControlDPsample.xaml
        /// </summary>
        public partial class UserControlDPsample : UserControl
        {
            public UserControlDPsample()
            {
                InitializeComponent();
            }
    
            public string ValueBC
            {
                get { return (string)GetValue(ValueBCProperty); }
                set { SetValue(ValueBCProperty, value); }
            }
            // Using a DependencyProperty as the backing store for Value.  This enables animation, styling, binding, etc...
            public static readonly DependencyProperty ValueBCProperty =
                DependencyProperty.Register("ValueBC", typeof(string), typeof(UserControlDPsample), new FrameworkPropertyMetadata("", new PropertyChangedCallback(FinalValueChanged)));
    
            private static void FinalValueChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
            {
            }
        }
    
        public class MyUserControlViewModel
        {
            public string hilh { get; set; }
        }

    Window: 

        <Window.Resources>
            <local:MainWindowViewModel x:Key="vm2222"></local:MainWindowViewModel>
        </Window.Resources>
    
        <Grid>
            <local:UserControlDPsample ValueBC="{Binding PName, Source={StaticResource vm2222} }"></local:UserControlDPsample>
        </Grid>

    Best regards

    Yong Lu


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Monday, November 25, 2019 4:14 AM
    Moderator

All replies

  • Hi,
    you can bind a property in the UserControl with RelativSource to the property from MainWindow:

    <UserControl x:Class="Window60UC1"
                 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:local="clr-namespace:WpfControlLibrary1"
                 mc:Ignorable="d" 
                 d:DesignHeight="450" d:DesignWidth="800">
      <UserControl.DataContext>
        <local:Window60UC1VM />
      </UserControl.DataContext>
      <Grid>
        <TextBlock Text="{Binding Path=PropUC.SomeValue, RelativeSource={RelativeSource AncestorType=UserControl}}"/>
      </Grid>
    </UserControl> 
    

    "PropUC" is the property in UserControl:

    Public Class Window60UC1
    
      Public Shared ReadOnly PropUCProperty As DependencyProperty =
                  DependencyProperty.RegisterAttached("PropUC",
                                              GetType(Window60UC1Data),
                                              GetType(Window60UC1),
                                              New PropertyMetadata(Nothing))
    
      Public Shared Function GetPropUC(obj As DependencyObject) As Window60UC1Data
        Return CType(obj.GetValue(PropUCProperty), Window60UC1Data)
      End Function
    
      Public Shared Sub SetPropUC(obj As DependencyObject, value As Window60UC1Data)
        obj.SetValue(PropUCProperty, value)
      End Sub
    
      Public Property PropUC As Window60UC1Data
        Get
          Return CType(GetValue(PropUCProperty), Window60UC1Data)
        End Get
        Set(value As Window60UC1Data)
          SetValue(PropUCProperty, value)
        End Set
      End Property
    
    End Class

    In the MainWindow you bind the UserControl's property to the property in the Main-ViewModel:

    <Window x:Class="Window60"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:WpfApp1"
            xmlns:uc="clr-namespace:WpfControlLibrary1;assembly=WpfControlLibrary1"
            mc:Ignorable="d"
            Title="Window60" Height="450" Width="800">
      <Window.Resources>
        <local:Window60VM x:Key="vm"/>
      </Window.Resources>
      <Grid>
        <uc:Window60UC1 PropUC="{Binding Path=PropMainVM, Source={StaticResource vm}}" />
      </Grid>
    </Window>

    The Main-ViewModel can look like this:

    Public Class Window60VM
      Public Property PropMainVM As WpfControlLibrary1.Window60UC1Data = New WpfControlLibrary1.Window60UC1Data With {.SomeValue = "TestValue from MainVM"}
    End Class

    And the data class with the property "SomeValue" can look like this:

    Public Class Window60UC1Data
      Public Property SomeValue As String = "Initial Data"
    End Class


    --
    Best Regards / Viele Grüße
    Peter Fleischer (former MVP for Developer Technologies)
    Homepage, Tipps, Tricks

    Saturday, November 23, 2019 8:30 AM
  • Hello. Basically, I'm trying to bind an object from my MainWindowViewModel to a custom UserControl, pass that object to data in the UserControl's ViewModel, and then display the data.

    <Window.DataContext>
        <viewmodels:MainWindowViewModel /
    </Window.DataContext>
    
    <controls:MyUserControl MyObjectProperty="{Binding Path=MyObject}" />

    And then the UserControl is basically like this...

    <UserControl.DataContext>
        <viewmodels:MyUserControlViewModel />
    </UserControl.DataContext>
    
    <TextBlock Text="{Binding Path=MyObject.SomeValue}" />

    The UserControl has its own ViewModel as well. And I notice when I don't set its DataContext I can bind my object but because I'm no longer using its ViewModel I can't pass the value to it for the backend logic.

    Am I maybe missing a RelativeSource reference of some kind that would allow me to bind to the UserControl, pass it to the ViewModel, and everything work?

    Thanks!

    Hi    T Gregory, 

    C# Version for your reference:

    UserControl:

      <UserControl.DataContext>
            <local:MyUserControlViewModel />
        </UserControl.DataContext>
        <Grid>
            <TextBox HorizontalAlignment="Left" Height="43" Margin="121,114,0,0" TextWrapping="Wrap" DataContext="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}" Text="{Binding ValueBC, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"  VerticalAlignment="Top" Width="350"/>
        </Grid>
    
    
        /// <summary>
        /// Interaction logic for UserControlDPsample.xaml
        /// </summary>
        public partial class UserControlDPsample : UserControl
        {
            public UserControlDPsample()
            {
                InitializeComponent();
            }
    
            public string ValueBC
            {
                get { return (string)GetValue(ValueBCProperty); }
                set { SetValue(ValueBCProperty, value); }
            }
            // Using a DependencyProperty as the backing store for Value.  This enables animation, styling, binding, etc...
            public static readonly DependencyProperty ValueBCProperty =
                DependencyProperty.Register("ValueBC", typeof(string), typeof(UserControlDPsample), new FrameworkPropertyMetadata("", new PropertyChangedCallback(FinalValueChanged)));
    
            private static void FinalValueChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
            {
            }
        }
    
        public class MyUserControlViewModel
        {
            public string hilh { get; set; }
        }

    Window: 

        <Window.Resources>
            <local:MainWindowViewModel x:Key="vm2222"></local:MainWindowViewModel>
        </Window.Resources>
    
        <Grid>
            <local:UserControlDPsample ValueBC="{Binding PName, Source={StaticResource vm2222} }"></local:UserControlDPsample>
        </Grid>

    Best regards

    Yong Lu


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Monday, November 25, 2019 4:14 AM
    Moderator