Pat
Pat

Reputation: 16891

Bind to a CheckBox and execute a command in a MVVM way

I have a question similar to this one, but in a more detailed situation. I am also trying to implement the solution using the Model View Viewmodel pattern.

In MainView, I have a button which calls a command (we'll call it Execute) stored in MainViewModel. I also want this command to be called when the left button of the mouse is clicked (actually, only on Up), but only when MouseUpCheckBox is checked.

When I had all the code in the view, I did static binding for Execute, but then used ElementName binding to the Window (named w_window) for IsChecked and checked the property value in the MouseLeftButtonUpEvent handler.

XAML

<Button Command="{x:Static local:MainView.Execute}">
    Execute
</Button>
<CheckBox IsChecked="{Binding ElementName=w_window, Path=ExecuteOnMouseUp}">
    Execute on Mouse Up
</CheckBox>

C#

public MainView()
{
    InitializeComponent();
    this.CommandBindings.Add(new CommandBinding(Execute, ExecuteExecuted));
    MyDesigner.AddHandler(UIElement.MouseLeftButtonUpEvent, new RoutedEventHandler((o, eventArgs) =>
    {
        if (ExecuteOnMouseUp)
        {
            Execute.Execute(null, this);
        }
    }), true);
}

#region ExecuteOnMouseUp
/// <summary>
/// ExecuteOnMouseUp Dependency Property
/// </summary>
public static readonly DependencyProperty ExecuteOnMouseUpProperty =
    DependencyProperty.Register("ExecuteOnMouseUp", typeof(bool), typeof(MainView),
        new FrameworkPropertyMetadata((bool)false));

/// <summary>
/// Gets or sets the ExecuteOnMouseUp property. This dependency property 
/// indicates ....
/// </summary>
public bool ExecuteOnMouseUp
{
    get { return (bool)GetValue(ExecuteOnMouseUpProperty); }
    set { SetValue(ExecuteOnMouseUpProperty, value); }
}
#endregion

#region Execute
/// <summary>
/// The Execute command ....
/// </summary>
public static RoutedUICommand Execute
    = new RoutedUICommand("Execute", "Execute", typeof(MainView));

private void ExecuteExecuted(object sender, ExecutedRoutedEventArgs e)
{
    ...
}
#endregion

How can I port this code from my view into the viewmodel? Should I use an attached property? Is there a way to bind the checkbox value to a parameter in the Command, or maybe in the CanExecute handler? What's the idiomatic WPF/MVVM way of dealing with this kind of situation?

Upvotes: 2

Views: 9376

Answers (2)

Alex Klaus
Alex Klaus

Reputation: 8934

Rachel provided a very good solution above, but in sake of comprehension I'm providing below details of different approach she mentioned (thanks to @Rachel again).

<...
 xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
...>
<i:Interaction.Triggers>
    <i:EventTrigger EventName="ExecuteOnMouseUp">
        <i:InvokeCommandAction Command="{Binding Execute}" />
    </i:EventTrigger>
</i:Interaction.Triggers>

I tried both and found some differences in handling routed events. But in general, both methods work like a charm.

Upvotes: 0

jbe
jbe

Reputation: 7031

In my opinion your example looks a bit too complicated for such a simple task as binding to a Button or a CheckBox.

You might have a look at the ViewModel sample application of the WPF Application Framework (WAF). It shows how you can bind the IsChecked property to the ViewModel in a MVVM friendly way.

Upvotes: 0

Related Questions