Reputation: 5779
I have a Canvas
that contains a Rectangle
. On that canvas, I bind a mousedown event to a command on the ViewModel. In that command, I am being passed the MouseEventArgs
, but there the Target element is either the Canvas
or the Rectangle
. Where can I find in the MouseEventArgs
the Canvas
this event was fired from?
My code is more or less:
<Canvas Background="White">
<i:EventTrigger EventName="MouseLeftButtonDown">
<local:InteractiveCommand Command="{Binding CmdMouseLeftButtonDown}"/>
</i:EventTrigger>
<Rectangle Width="50" Height="50" />
</Canvas>
And in the ViewModel:
ICommand CmdMouseLeftButtonDown => new DelegateCommand<MouseEventArgs>(e =>
{
e.??? // <= Where do I find the Canvas here, whether I click on the Rectangle or Canvas?
}
Please do not answer with some hackish solution like e.MouseDevice.Target.Parent
. This needs to work however complicated the element in the canvas is. It could contain another canvas for instance.
Upvotes: 0
Views: 2085
Reputation: 870
Set <Canvas Background="Transparent" ... />
as answered in the following question by @Rob Fonseca-Ensor:
WPF: Canvas mouse events not firing on empty space
Upvotes: 0
Reputation: 169350
A view model is not supposed to have a reference to a UI element such as a Canvas
or a Rectangle
at all in the first place. This effectively breaks the MVVM pattern and that's why it makes no sense to pass the sender
argument to the command.
You might as well get rid of the EventTrigger
and invoke the command programmatically from the code-behind of the view:
<Canvas Background="White" MouseLeftButtonDown="Canvas_MouseLeftButtonDown">
<Rectangle Width="50" Height="50" Fill="Red" />
</Canvas>
private void Canvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
var yourViewModel vm = DataContext as YourClass;
vm.CmdMouseLeftButtonDown.Execute(sender as Canvas); //<-- pass the Canvas as a command argument or create a new command argument type that holds a reference to the Canvas
}
This is certainly not any worse than your current approach as far as the MVVM pattern is concerned. You are still invoking the very same command from the very same view and MVVM is not about eliminating code. It is about separation of concerns.
Upvotes: 1
Reputation: 33381
Your MouseEventArgs.Source
will reference to the Canvas
in any case but the MouseEventArgs.OriginalSource
will referece to the Rectange
if you have clicked on its area. It will be the control determined by pure hit testing.
Upvotes: 0