views:

85

answers:

3

I have a usercontrol with a command, what I would like to do is execute this command from the containing view's ViewModel.

This would be easy to accomplish in the code behind, as I could just go "UserControl.MyCommand.Execute", but of course I want to be able to do this in the ViewModel.

In theory, what I would like to do is bind the UserControl's Command to a Command on the ViewModel which I can execute and will then be handled by the UserControl. Something like this:

...
<local:MyControl
         MyCommand="{Binding ViewModelsCommand}" />
...

Of course this will have the opposite affect to what I want to do, as now the ViewModelsCommand is bound to MyCommand. So how to invert this?

Basically I want to be able to bind something like this:

ViewModelsCommand="{Binding MyControl.MyCommand}"

Any ideas or inspiration would be welcomed, I can't see a binding Mode that would let me do this. And I'm not sure how to access the DataContext's properties for binding (usually you would do just bind and have twoway handle this, but of course that doesn't work in this scenario).

Thanks in advance.

A: 

Please note, the following answer is not correct. It seems that OneWayToSource only updates after the target-property has changed. However I don't delete this answer to inform other people which are not aware of this behaviour (like me).

Old answer (see text above)

IMO your example should work (if MyControl.MyCommand is a public property that returns an ICommand). Have you tried the BindingMode OneWayToSource?

<local:MyControl 
         MyCommand="{Binding ViewModelsCommand,Mode=OneWayToSource}" /> 
HCL
Yes I have, but when I do, I get MyCommand is ViewModelsCommand, which is not what I want. I want ViewModelsCommand to be MyCommand. Does that make sense? Sorry if I'm not explaining this well
Chris Nicol
I'm surprised by this behaviour. Have you checked if you have some old test-code in the code-behind or at another location that overrides this binding? May be a Binding declared in code or even a static assignment? If this is not the problem, create and attach a value converter that does nothing than returning the input value and then set a breakpoint in the two conversion-methods. After that you will see, when which object is moved from where to where. I don't have another idea. As far as I understand, the Binding must exactly do what you desire, not the opposite.
HCL
@HCL The source will only be updated if the target property changes, which it never will. As far as I know, `OneWayToSource` does not set the source when initially bound.
Jay
Sorry HCL, Jay is right, OneWayToSource doesn't work for me in this way. I've been trying to think of a way to explain this better, but I think it's basically Daisy Chaining commands?!?!
Chris Nicol
@Jay and @Chris Nicol: Thanks, I was not aware of this (obviously:). I will delete my post in a few minutes to not lead other people in the wrong direction.
HCL
@HCL I'd leave it. It is a reasonable approach; others may wonder why not do that.
Jay
@Jay: Your right, I will not delete.
HCL
Thanks for not deleting HCL, it was a good attempt. I'm glad it's there for clarity and to help others.
Chris Nicol
A: 

I use PRISM's EventAggregator, or MVVMLight's Messenger to allow two ViewModels to talk, but your case looks slightly different where you have a view(UserControl) talking to a ViewModel.

JoshVarga
Yup, and what I want to accomplish shouldn't need the level of complexity that would be added by using something like Messenger. I'm not saying that Messenger is complex, just that I basically want to pass a command down the visual tree.
Chris Nicol
+1  A: 

You are instantiating the view-model in the constructor of the view.

Why not set the value explicitly upon construction?

 public SomeView()
 {
      var viewModel = new SomeViewModel();
      viewModel.ViewModelCommand = MyCommand; // or = myControl.MyCommand

      DataContext = viewModel;
 }

It is possible to use a binding with OneWayToSource, TwoWay, or Explicit, but you still have to explicitly update source at least once in code (always if you use Explicit).

myControl.GetBindingExpression(MyControl.MyCommandProperty).UpdateSource();
Jay
Jay, I like this approach and I will implement this for the current problem. However, I would still like to solve the problem through binding. It must be possible and I believe it would be a handy approach if it did.
Chris Nicol
@Chris I update the answer with more info about using a binding.
Jay