I have a custom style in a separate XAML CustomTabItem.xaml
which raises an event like:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="myProject.CustomTabItem">
...
...
<MenuItem Header="One">
<MenuItem.Style>
<Style TargetType="{x:Type MenuItem}">
<EventSetter Event="Click" Handler="ClickNewSpaceOne"/>
</Style>
</MenuItem.Style>
</MenuItem>
...
...
</ResourceDictionary>
And this easily raises an event in a file I created called CustomTabItem.xaml.cs
:
namespace myProject
{
partial class CustomTabItem
{
private void ClickNewSpaceOne(object sender, RoutedEventArgs e)
{
//do stuff here
}
}
}
This all works fine, but I now need to raise an event in the MainWindow
(of course in the event handler ClickNewSpaceOne
) but I cannot figure out how to propagate this event to the MainWindow
.
I found this article but it doesn't really look like the same situation, so any different article that I didn't find or any answer I would really appreciate.
The practice of using EventSetter
in this case, not the best. And here's why:
Because it, is limited to the global function of the event, he just looking event handler in xaml.cs
file. Also, because of this, from MSDN
:
Event setters cannot be used in a style that is contained in a theme resource dictionary.
EventSetter
can not be set in the TriggerQuote from link
:
Because using EventSetter to wire up event handler is a compile-time feature which is plumbed through IStyleConnector interface, there is another interface called IComponentConnector which is used by the XAML compiler to wire up event handler for standalone XAML elements.
What alternatives?
1 - Attached dependency property
Use the attached dependency property and its UIPropertyMetadata
, you implement the necessary logic. For example:
// GetValue
// SetValue
public static readonly DependencyProperty SampleProperty =
DependencyProperty.RegisterAttached("Sample",
typeof(bool),
typeof(SampleClass),
new UIPropertyMetadata(false, OnSample));
private static void OnSample(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
if (e.NewValue is bool && ((bool)e.NewValue) == true)
{
// do something...
}
}
More information can be found here:
How to inherit Button behaviour in WPF style?
Quit application from a user Control
How to clear the contents of a PasswordBox when login fails without databinding?
2 - Commands
Command in the WPF is a very powerful. Quote from MSDN
:
The first purpose is to separate the semantics and the object that invokes a command from the logic that executes the command. This allows for multiple and disparate sources to invoke the same command logic, and it allows the command logic to be customized for different targets.
In this case, they can and should be used in Styles
, Templates
, DataTemplates
. In style, you can set a command like this:
<Setter Property="Command"
Value="{Binding DataContext.YourCommand,
RelativeSource={Relative Source AncestorType={x:Type Control}}}">
Also, if you want to reference the command, you can declare the command as a static property then you can use Static
extention to reference it.
3 - Using EventTrigger with Interactivity
In this case, the command is called by the EventTrigger
. For example:
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseEnter" >
<i:InvokeCommandAction Command="{Binding MyCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
More information, can be founded here: