Question

Here's a little background before I start. I started creating my application in WPF the same way I used to program in WinForms. Obviously, this is completely bypassing the strength of WPF. So now that I've read more on WPF and the MVVM framework, I'm starting to adapt my application to work in the Model - View - ViewModel way.

Beforehand, I used to have code-behind of my Window and just handled the MouseDown RoutedEvents to then proceed and prompt a window for a signature. My DockPanel and Image don't seem to have a Command.

How can I do this the MVVM way? Are RoutedEvents the way to go for this situation?

Was it helpful?

Solution

Instead of complicating the whole thing with Behaviors and stuff, put all your UI elements inside the ControlTemplate of a Button and use it's Command:

<Button Command="{Binding YourCommand}">
   <Button.Template>
      <ControlTemplate TargetType="Button">
          <DockPanel>
             <Image/>
             <!-- Whatever -->
          </DockPanel>
      </ControlTemplate>
   </Button.Template>
</Button>

OTHER TIPS

You can use interactivity triggers which comes with Blend SDK.

Steps -

  • Add a reference to assembly System.Windows.Interactivity.

  • Add a corresponding namespace in XAML file

    xmlns:interactivity="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"

You can use it like for an example -

<StackPanel>
   <interactivity:Interaction.Triggers>
      <interactivity:EventTrigger EventName="MouseDown">
        <interactivity:InvokeCommandAction Command="{Binding CloseCommand}"/>
      </interactivity:EventTrigger>
   </interactivity:Interaction.Triggers>            
</StackPanel>

Here CloseCommand is in your ViewModel class.

For implement Image click:

  1. Write a class that extends System.Windows.Control.Image.
  2. Create a RoutedEvent and RoutedEventHandler to facilitate the mouse click event.
  3. Override OnMouseLeftButtonDown

In my example, I evaluate the click count, because have not idea how do this better

public class ImageHelper : Image
    {
        public static readonly RoutedEvent MouseLeftButtonClick =
            EventManager.RegisterRoutedEvent(
                "MouseLeftButtonClick",
                RoutingStrategy.Bubble,
                typeof(RoutedEventHandler),
                typeof(ImageHelper));

        public event RoutedEventHandler MouseLeftButtonClickEvent
        {
            add
            {
                AddHandler(MouseLeftButtonClick, value);
            }
            remove
            {
                RemoveHandler(MouseLeftButtonClick, value);
            }
        }

        protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
        {
            if (e.ClickCount == 1)
            {
                RaiseEvent(new MouseLeftButtonClickEventArgs(
                    MouseLeftButtonClick, this));
            }
            base.OnMouseLeftButtonDown(e);
        }

        public class MouseLeftButtonClickEventArgs : RoutedEventArgs
        {
            public MouseLeftButtonClickEventArgs(RoutedEvent routedEvent, object source)
                : base(routedEvent, source)
            {
               // some code.....
            }
        }
    }

XAML:

<local:ImageHelper>
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="MouseLeftButtonClickEvent">
                    <i:InvokeCommandAction Command="{Binding Path=MyCommand}" />
                </i:EventTrigger>
            </i:Interaction.Triggers>
 </local:ImageHelper>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top