简体   繁体   中英

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)

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;
    }
}

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 DependencyProperty s 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM