22

I created a Dependency Property in the usercontrol, but however changes in the usercontrol was NOT notified to the Viewmodel

Usercontrol

<UserControl x:Class="DPsample.UserControl1"
         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" 
         d:DesignHeight="300" d:DesignWidth="300">
<Grid>
    <TextBox x:Name="txtName"></TextBox>
</Grid>

UserControl.cs

/// <summary>
/// Interaction logic for UserControl1.xaml
/// </summary>
public partial class UserControl1 : UserControl
{
    public UserControl1()
    {
        InitializeComponent();
    }

    #region SampleProperty 

    public static readonly DependencyProperty SamplePropertyProperty
                                            = DependencyProperty.Register("SampleProperty", 
                                            typeof(string), 
                                            typeof(UserControl1), 
                                            new PropertyMetadata(OnSamplePropertyChanged));


    public string SampleProperty
    {
        get { return (string)GetValue(SamplePropertyProperty); }
        set { SetValue(SamplePropertyProperty, value); }
    }


    static void OnSamplePropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
    {
        (obj as UserControl1).OnSamplePropertyChanged(e);
    }
    private void OnSamplePropertyChanged(DependencyPropertyChangedEventArgs e)
    {
        string SamplePropertyNewValue = (string)e.NewValue;

        txtName.Text = SamplePropertyNewValue;
    }

    #endregion
}

MainWindow

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:DPsample" x:Class="DPsample.MainWindow"
    Title="MainWindow" Height="350" Width="525">
<Grid>

    <local:UserControl1 SampleProperty="{Binding SampleText,Mode=TwoWay}" HorizontalAlignment="Left" Margin="76,89,0,0" VerticalAlignment="Top" Width="99"/>
    <Button Content="Show" HorizontalAlignment="Left" Margin="76,125,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click"/>

</Grid>

MainWindow.cs

 public MainWindow()
    {
        InitializeComponent();
        this.DataContext = new MainViewModel();
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        var item = this.DataContext as MainViewModel;
        MessageBox.Show(item.SampleText.ToString());
    }

MainViewModel.cs

public class MainViewModel : NotifyViewModelBase
{
    public MainViewModel()
    {
        this.SampleText = "test";           
    }

    private string _sampleText;
    public string SampleText
    {
        get { return _sampleText; }
        set { _sampleText = value; OnPropertyChanged("SampleText"); }
    }
}
3
  • You haven't coded anything that passes changes of the TextBox.Text property to SampleProperty. You should also use a binding there, with RelativeSource={RelativeSource AncestorType=UserControl}. Commented Sep 23, 2014 at 7:16
  • @Clemens do i need to use the viewmodel for the usercontrol? Commented Sep 23, 2014 at 7:23
  • Not in this case. However, the UserControl might as well directly bind to your view model's SampleText property. Then there would be no need at all for SampleProperty. Commented Sep 23, 2014 at 7:28

2 Answers 2

67

Bind the TextBox.Text property in the UserControl to its SampleProperty like this:

<TextBox Text="{Binding SampleProperty,
                RelativeSource={RelativeSource AncestorType=UserControl}}"/>

Now you could simply remove your OnSamplePropertyChanged callback.


You might also register SampleProperty to bind two-way by default like this:

public static readonly DependencyProperty
    SamplePropertyProperty = DependencyProperty.Register(
        "SampleProperty", typeof(string), typeof(UserControl1),
        new FrameworkPropertyMetadata(
            null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
Sign up to request clarification or add additional context in comments.

1 Comment

Can't believe I've read so many tutorials and examples on custom UserControls and DependencyProperties and not one mentions the FrameworkPropertyMetadata that solves passing the value back to the model. Great job man!
4

An alternative way to do this is an ElementName Binding. First assign the x:Name attribute to the UserControl (for example x:Name="MyUC"), then change the binding to:

<TextBox Text="{Binding ElementName=MyUC, Path=SampleProperty}"/>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.