2
votes

I'm still trying to wrap my head around some of the finer points of using WPF and MVVM. One thing that has bugged me for a while is how to get values from the View into the ViewModel. Let me explain the scenario.

I have a Window with several UserControls inside. One of those UserControls has a DependencyProperty of type TimeSpan named CurrentTime. It is bound (in the XAML for the window) to the Window's ViewModel.

Now, I also have a ViewModel for the UserControl. It needs access to the CurrentTime property in order to create objects based off it. How do I get that value into my ViewModel? I see a couple of options:

  1. The simplest is probably just to pass the View into the ViewModel's constructor (or somehow otherwise reference the View from the ViewModel). But that seems so wrong and not WPF/MVVMy.
  2. I could use messaging to actually get the CurrentTime from the other ViewModel. This would certainly work, but seems like overkill.
  3. I could set up a binding in the XAML of the UserControl to bind, OneWayToSource, between the DP and the property in the ViewModel. I can't figure out exactly how to set that up (how do you reference a UserControl's new properties in its own XAML?), but it seems like it could work.

Am I missing any other options? Which of the above (or ones I missed) is the best way to do this?

I read through this thread here on SO, because it was similar, but the answers didn't really answer my question - I would love to do it with bindings or commands or something, but I just can't figure out how exactly.

1
Or.. your outer viewmodel bound to the window has a property that serves as the data context for the user control. This really just exposes the user control viewmodel as part of the window viewmodel, which may or may not be a design issue for you.Marc
@Marc - Thanks for the comment. In my situation the UserControl is used in a number of locations. Theoretically I could move its VM out into each of those outer VM's, but its a decent amount of logic in there that I felt should be encapsulated. That said, its another approach I'll have to ponder.Tim
I think your best bet is with messaging. If as you state you have several instances of the usercontrol used throughout the application and they need to know the current time from the main app, then you make them receivers and the mainwindow fires off the message when needed. personally I think you need to look at what your actual goal with this control is and verify your design.ecathell

1 Answers

4
votes

The third option is the way to go here, but you'll have to specify binding in the code-behind of your UserControl:

public partial class MyUserControl : UserControl
{
    public MyUserControl() {
        InitializeComponent();

        SetBinding(MyPropertyProperty,
                   new Binding {Path = new PropertyPath("MyViewModelProperty"), Mode = BindingMode.OneWayToSource});
    }
}