MVVM way to wire up event handlers in Silverlight

2019-05-30 10:40发布

问题:

Using an MVVM pattern in Silverlight/WPF, how do you wire up event handers? I'm trying to bind the XAML Click property to a delegate in the view model, but can't get it to work.

In other words, I want to replace this:

<Button Content="Test Click" Click="Button_Click" />

where Button_Click is:

private void Button_Click(object sender, RoutedEventArgs e) 
{ 
    // ...
}

with this:

<Button Content="Test Click" Click="{Binding ViewModel.HandleClick}" />

where HandleClick is the handler. Attempting this throws a runtime exception:

Object of type 'System.Windows.Data.Binding' cannot be converted to type 'System.Windows.RoutedEventHandler'.

回答1:

The MVVM way to do so is by using commands and the ICommand interface. The Button control has a property named Command which receives an object of type ICommand

A commonly used implementation of ICommand is Prism's DelegateCommand. To use it, you can do this in your view model:

public class ViewModel
{
    public ICommand DoSomethingCommand { get; private set; }

    public ViewModel()
    {
        DoSomethingCommand = new DelegateCommand(HandleDoSomethingCommand);
    }

    private void HandleDoSomethingCommand()
    {
        // Do stuff
    }
}

Then in XAML:

<Button Content="Test Click" Command={Binding DoSomethingCommand} />

Also, make sure that the viewmodel is set as your view's DataContext. One way to do so is in your view's code-behind:

this.DataContext = new ViewModel();

This article is a good place to start if you want to know more about MVVM.



回答2:

The answer is to use the extensions provided by Microsoft in the Prism framework. With the DLLs System.Windows.Interactivity.dll and Microsoft.Expression.Interactions.dll, it's possible to bind an event to a handler method in a view model:

<Button Content="Test Click"
    xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"      
    xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
    >
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="Click">
            <ei:CallMethodAction TargetObject="{Binding ViewModel}" MethodName="HandleClick" />
        </i:EventTrigger>
    </i:Interaction.Triggers>
</Button>