tzuhsun
tzuhsun

Reputation: 101

Bind a method to xaml control

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

Answers (4)

tzuhsun
tzuhsun

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

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

MiVVM UML Diagram

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

ColinE
ColinE

Reputation: 70122

There are two different approached which you can use:

  • Commands, expose a property of type ICommand which you bind to Command properties of your UI elements.
  • Use behaviours to wire a UI event to a method in your view model, for example use the MVVM Light EventToCommandBehaviour.

Upvotes: 2

ChrisBD
ChrisBD

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

Related Questions