Could you be more specific on what the conditions are? @ColineE and @ChrisBD correctly point out that ICommands and EventTocommandBehavior are going to help in many circumstances, such as translating a button click or a mouseover event into a method call in a ViewModel. I would advocate using these approaches if they can be used as they are deemed best practice
However, some cases require something a little more complex than that. One solution is to use code-behind to cast the DataContext to a view model type and invokle the method directly. For instance:
// Inside MyViewModel.cs
public class MyViewModel : INotifyPropertyChanged
{
// ...
}
// ...
// Inside MyControl.xaml.cs
public class MyControl : UserControl
{
public MyControl()
{
InitializeComponent();
}
pubilc void OnSomeConditionMatches()
{
var myViewModel = DataContext as MyViewModel;
if (myViewModel != null)
{
// Hacky, but it works
myViewModel.CallCustomMethod();
}
}
}
This is considered a little hacky and pollutes the code-behind with knowledge of the ViewModel type at runtime. Something we want to avoid as it breaks the separation of concerns between View and ViewModel.
Another method is something I've used myself when dealing with a custom control that has little or no databinding support. By using an interface on the view and an attached property you can inject a view instance into the viewModel and manipulate it directly. Sort of a hybrid MVVM / MVP pattern which I've coined MiVVM.
UML

Xaml:
<!-- Assumes myViewModel is the viewmodel we are binding to -->
<!-- which has property InjectedUserControl of type IMyControl -->
<Example3:MyControl DataContext="{StaticResource myViewModel}"
Injector.InjectThisInto="InjectedUserControl">
</Example3:MyControl>
Code:
// Defines an interface to the usercontrol to
// manipulate directly from ViewModel
public interface IMyControl
{
// Our test method to call
void CallView(string message);
}
// Defines the usercontrol
public partial class MyControl : UserControl, IMyControl
{
public MyControl()
{
InitializeComponent();
}
public void CallView(string message)
{
MessageBox.Show(message);
}
}
public class MyViewModel
{
private IMyControl myControl;
public IMyControl InjectedUserControl
{
set
{
Debug.WriteLine(string.Format("Received Injected Control \"{0}\"",
value == null ? "NULL" : value.GetType().Name));
this.myControl = value;
this.OnInjectedObjectsChanged();
}
}
private void OnInjectedObjectsChanged()
{
// Directly access the view via its interface
if (this.myControl != null)
this.myControl.CallView("Hello From MyViewModel");
}
}
For a downloadable demo including the source for the Injector attached property, please see this blog post. Also this previous question which is related.
Best regards,