So you want to react to some events happening in the UI. First things first: if you want, in reaction, to change only your view/layout, you do not need ICommand
and a simple event handler will do the trick. If you expect to change the underlying data (your view model) in reaction to that event, you can use an ICommand
or an event handler, as described below.
Let's first define a simple view model for our MainWindow
:
public class MyViewModel {
/// <summary>
/// Command that performs stuff.
/// </summary>
public ICommand MyCommand { get; private set; }
public MyViewModel() {
//Create the ICommand
MyCommand = new RelayCommand(() => PerformStuff());
}
public void PerformStuff() {
//Do stuff that affects your view model and model.
//Do not do anything here that needs a reference to a view object, as this breaks MVVM.
Console.WriteLine("Stuff performed in ViewModel.");
}
}
This assumes that you have a RelayCommand
implementation of the ICommand
interface that lets you invoke Action
delegates on Execute
:
public class RelayCommand : ICommand {
//Saved Action to invoke on Execute
private Action _action;
/// <summary>
/// ICommand that always runs the passed <paramref name="action"/> when executing.
/// </summary>
/// <param name="action"></param>
public RelayCommand(Action action) {
_action = action;
}
#region ICommand
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter) => true;
public void Execute(object parameter) => _action.Invoke();
#endregion
}
In your MainWindow.xaml, we define two Border
objects: the first one operates on the view model through an event handler, the second one through the ICommand
pattern:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<!--Performs action on click through event handler-->
<Border Grid.Row="0" MouseUp="Border_MouseUp" Background="Red"></Border>
<!--Performs action on click through ICommand-->
<Border Grid.Row="1" Background="Blue">
<Border.InputBindings>
<MouseBinding MouseAction="LeftClick" Command="{Binding MyCommand}"></MouseBinding>
</Border.InputBindings>
</Border>
</Grid>
In your MainWindow.xaml.cs, assign a view model object and define the event handler for mouse up event:
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
DataContext = new MyViewModel(); ;
}
//Handles mouse up event on the first Border
private void Border_MouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e) {
//...
//Do stuff that affects only your view here!
//...
//Now the stuff that affects the view model/model:
((MyViewModel)DataContext).PerformStuff();
}
}
Clicking on any of the two Border
objects will perfom stuff on your view model.
How to apply this to your specific control and event?
You can always use a custom event handler DockingManager_LayoutChanged
as shown above.
If you want to use the ICommand
and your event is something else than a mouse or keyboard event, you can achieve the binding by following this instead of using a MouseBinding
.