I have a template with a Style
that uses an EventSetter
to set a common event handler to some Hyperlink
s. But I want to handle this event not in the resource dictionary's .cs
file but in the custom control's .cs
file. How can I do this? I am in the process of moving resources into theme .xaml
files. I thought about separating the functionality part of the Hyperlink style, but where should I put the event setter? I thought I can use commands, but is there a more concise tehnique that does not require changing each Hyperlink
element and works for elements that do not support commands?
I use .NET Framework 4.7.2. I have made a few searches over the web and a simple test example:
App.xaml
<Application x:Class="wpf_test_2.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:wpf_test_2"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Dictionary.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
Dictionary.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:wpf_test_2">
<ControlTemplate x:Key="MyControlTemplate">
<ControlTemplate.Resources>
<Style TargetType="Button">
<!-- obviously, this does not compile: -->
<EventSetter Event="Click" Handler="MyHandler"/>
</Style>
</ControlTemplate.Resources>
<UniformGrid Rows="5" Columns="5">
<Button>A</Button>
<Button>B</Button>
<Button>C</Button>
<Button>D</Button>
<Button>E</Button>
<Button>F</Button>
<Button>G</Button>
<Button>H</Button>
<Button>I</Button>
</UniformGrid>
</ControlTemplate>
</ResourceDictionary>
MainWindow.xaml
<Window x:Class="wpf_test_2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:wpf_test_2"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<local:MyControl/>
</Grid>
</Window>
MyControl.xaml
<Control x:Class="wpf_test_2.MyControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:wpf_test_2"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
Template="{DynamicResource MyControlTemplate}">
</Control>
MyControl.xaml.cs
/// <summary>
/// Interaction logic for MyControl.xaml
/// </summary>
public partial class MyControl : Control
{
public MyControl()
{
InitializeComponent();
}
private void MyHandler(object sender, RoutedEventArgs e)
{
var b = sender as Button;
MessageBox.Show($"Button {b.Content.ToString()} was clicked!");
}
}
Screenshot
Expected: the project compiles, and when I click one of the buttons, a MessageBox appears with the content of the button as string.
Actual: the project does not compile.
Thank you.
Inspired by Clemens' comment, I created a
RoutedUICommand
, a corresponding command binding, and setters which setCommand
andCommandParameter
:AboutWindow.xaml
AboutWindow.xaml.cs
Light.xaml