NKnusperer
NKnusperer

Reputation: 984

Dependency Property + UserControl + ViewModel

Given I have this UserControl:

public class MyStringUserControl : UserControl
{
    public string MyString
    {
        get { return (string)GetValue(MyStringProperty); }
        set { SetValue(MyStringProperty, value); }
    }

    public static readonly DependencyProperty MyStringProperty =
        DependencyProperty.Register("MyString", typeof(string), typeof(MyStringUserControl),
            new FrameworkPropertyMetadata(null));
}

And this ViewModel:

public class MyStringViewModel
{
    public string MyString { get; set; }
}

Now I use the MyStringUserControl in another View like this:

<controls:MyStringUserControl MyString="{Binding SomeStringProperty} />

I'am looking for an elegant way to bind this string back to the MyStringViewModel.
I also don't feel comfortable with the fact that I have to duplicate every property in the UserControl code behind and ViewModel. Is there a better way to do this?

Edit #1:

The reason I want to do this is because of unit testing (creating a UserControl takes very long even without InitializeComponent)

Upvotes: 0

Views: 1738

Answers (2)

Sheridan
Sheridan

Reputation: 69959

There is absolutely no point in duplicating your properties. Using MVVM does not mean that you need to have a view model for every UserControl. When I use a UserControl as a part of a view, I rarely use a separate view model for it. Sometimes, I'll just use the DependencyPropertys in the UserControl code behind, while other times I'll just data bind to the parent view model directly. It all depends on what you want to do with the data.

Upvotes: 2

Derrick Moeller
Derrick Moeller

Reputation: 4950

If I was intent on doing this, I would use DependencyProperty's PropertyChanged event handler to set my ViewModel's property, and my ViewModel's PropertyChanged event handler to set my DependencyProperty. Having said that I've never had a reason to go down this particular road.

private SomeViewModel _viewModel;

public static readonly DependencyProperty MyStringProperty = DependencyProperty.Register("MyString", typeof(string), typeof(MyStringUserControl), new PropertyMetadata(OnMyStringChanged));

public MyStringUserControl()
{
    InitializeComponent();

    _viewModel = new SomeViewModel();
    _viewModel.PropertyChanged += OnViewModelPropertyChanged;

    this.DataContext = _viewModel;
}

private static void OnMyStringChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    ((MyStringUserControl)d).OnMyStringChanged(e.NewValue);
}

private void OnMyStringChanged(string newValue)
{
    _viewModel.SomeProperty = newValue;
}

private void OnViewModelPropertyChanged(object sender, PropertyChangedEventArgs e)
{
    switch (e.PropertyName)
    {
        case "SomeProperty":
            SetValue(MyStringProperty, _viewModel.SomeProperty);
            break;
        default:
            break;
    }
}

Upvotes: 0

Related Questions