Reputation: 101
I need to bind a method to a custom control in xaml file, NOT the result of the method.
Basically the custom control will trigger the method few times when certain conditions match.
How can I do that?
I found some solutions in internet but most of them are binding the result of method into xaml, which is not the solution I looking for.
Many thanks.
Upvotes: 3
Views: 3006
Reputation: 101
Found this great answer:
Binding of static method/function to Func<T> property in XAML
Simon Rasmussen already shows all I need in his question sample code.
Upvotes: 2
Reputation: 21521
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,
Upvotes: 1
Reputation: 70122
There are two different approached which you can use:
ICommand
which you bind to Command properties of your UI elements.Upvotes: 2
Reputation: 9209
You'll be wanting to bind to an implementation of ICommand and have that call your class method.
Here's a good blog describing more about using ICommand to execute code from WPF.
Upvotes: 0