How to set an event function via a style?

29,032

Martin,

you can assign an event handler directly from a style using an EventSetter:

<Style TargetType="{x:Type Button}">
  <EventSetter Event="Click" Handler="SomeAction"/>
</Style>

@ColinE:

I am not sure that using a style to perform event wire-up is a good idea. Styles, by definition, define the visual appearance of controls.

Unfortunately, this seems to be a common and widespread misconception about WPF styles: Although their name suggests they are, like what you say, merely meant to define the visual appearance, they are actually much more: It is helpful to view styles more generally as a shortcut for assigning a set of properties to a control.

Share:
29,032
Martin Hennings
Author by

Martin Hennings

(my about me is currently blank)

Updated on July 09, 2022

Comments

  • Martin Hennings
    Martin Hennings almost 2 years

    I have several GUI control elements of which some are supposed to generate the same action (code-behind function call) on mouse interaction (MouseEnter, MouseLeave).
    [edit] I am performing some non style related functionality in my event handlers.
    Right now I'm using event attributes in each control:

    <Button Name="Button" Content="Button 1" 
        MouseEnter="GeneralMouseEnter" MouseLeave="GeneralMouseLeave" 
        PreviewMouseDown="Button1_PreviewMouseDown" PreviewMouseUp="Button1_PreviewMouseUp" />
    <Button Name="NotInteractingButton" Content="Button 2" 
        /><!-- this button has no MouseOver-effects -->
    <ToggleButton Content="ToggleButton" 
        MouseEnter="GeneralMouseEnter" MouseLeave="GeneralMouseLeave"  />
    <!-- needs to use IsMouseDirectlyOver on the slider knob... -->
    <Slider Name="HorizontalSlider" 
        MouseEnter="GeneralMouseEnter" MouseLeave="GeneralMouseLeave" 
        ValueChanged="Slider_ValueChanged" />
    <Slider Name="VerticalSlider" Orientation="Vertical" 
        MouseEnter="GeneralMouseEnter" MouseLeave="GeneralMouseLeave" 
        ValueChanged="Slider_ValueChanged" />
    

    Since many controls in this example are calling the same two functions "GeneralMouseEnter" and "GeneralMouseLeave", I'd like to be able to define a style or something similar to encapsulate that behavior.

    [edit - clarification]
    This is supposed to become a kind of plugin later on.
    (Include code and XAML files to any GUI program and set a style on each interactive control element...)

    From what I found on the web, I can use EventTriggers like in this example:

    <Style.Triggers>
      <EventTrigger RoutedEvent="Click">
        <EventTrigger.Actions>
          <BeginAction TargetName="SomeAction" />
        </EventTrigger.Actions>
      </EventTrigger>
    </Style.Triggers>
    

    I don't know though if and how to call functions within an action.

    • Is it possible to get this functionality by creating a style with action + trigger to be applied to each control? How to do that?
    • How do I assign multiple styles (for multiple interaction events) to one control?
    • Is there maybe even a cleaner way to achieve this behavior?
    • [edit]
      What if I want to, let's say, have mouse interaction on all sliders in my GUI?
  • Martin Hennings
    Martin Hennings over 13 years
    Great, that's exactly what I was searching for - especially in combination with BasedOn="...".
  • luka
    luka over 5 years
    This works only if you use the style tag under the class. If you use this in a separate dictionary this error was thrown: 'ResourceDictionary' root element requires a x:Class attribute to support event handlers in the XAML file. Either remove the event handler for the Click event, or add a x:Class attribute to the root element. obviously the X:Class attribute in dictionary can't used, if the dictionary is a merged dictionary in class.
  • Brains
    Brains almost 4 years
    The event inside EventSetter must be a RoutedEvent (not works with TargetUpdated)
  • Brains
    Brains almost 4 years
    @Ghosthack However, specifically for TargetUpdated a workaround exists Binding.TargetUpdated