From 51977cea61cb52299ba26ab78d0fc802d62813d8 Mon Sep 17 00:00:00 2001 From: Tris Shores <86677757+v-trisshores@users.noreply.github.com> Date: Thu, 10 Feb 2022 16:49:46 -0600 Subject: [PATCH] Content update - How to create a custom routed event (user story 1878475) (#1289) * Add article, redirects, toc * Update dotnet-desktop-guide/net/wpf/events/how-to-create-a-custom-routed-event.md Co-authored-by: Andy (Steve) De George <67293991+adegeo@users.noreply.github.com> * Update dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/csharp/CodeSample.csproj Co-authored-by: Andy (Steve) De George <67293991+adegeo@users.noreply.github.com> * Update dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/vb/CodeSampleVb.vbproj Co-authored-by: Andy (Steve) De George <67293991+adegeo@users.noreply.github.com> * Update dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/WpfControlLibraryCsharp/WpfControlLibrary.csproj Co-authored-by: Andy (Steve) De George <67293991+adegeo@users.noreply.github.com> * Use local project references Co-authored-by: Andy (Steve) De George <67293991+adegeo@users.noreply.github.com> --- .openpublishing.redirection.json | 8 ++ .../how-to-create-a-custom-routed-event.md | 82 ++++++++++++ .../WpfControlLibraryCsharp/CustomButton.cs | 45 +++++++ .../WpfControlLibrary.csproj | 9 ++ .../WpfControlLibraryVb/CustomButton.vb | 53 ++++++++ .../WpfControlLibraryVb.vbproj | 10 ++ .../csharp/App.xaml.cs | 11 ++ .../csharp/AssemblyInfo.cs | 10 ++ .../csharp/CodeSample.csproj | 29 +++++ .../csharp/MainWindow.xaml | 17 +++ .../csharp/MainWindow.xaml.cs | 42 ++++++ .../csharp/Properties/Resources.Designer.cs | 63 +++++++++ .../csharp/Properties/Resources.resx | 120 ++++++++++++++++++ .../csharp/WpfControlLibrary.dll | Bin 0 -> 5632 bytes .../csharp/app.xaml | 9 ++ .../vb/Application.xaml | 9 ++ .../vb/Application.xaml.vb | 6 + .../vb/AssemblyInfo.vb | 9 ++ .../vb/CodeSampleVb.vbproj | 27 ++++ .../vb/MainWindow.xaml | 17 +++ .../vb/MainWindow.xaml.vb | 39 ++++++ .../vb/WpfControlLibraryVb.dll | Bin 0 -> 5120 bytes dotnet-desktop-guide/net/wpf/toc.yml | 2 + redirects_generator/definitions.json | 5 + 24 files changed, 622 insertions(+) create mode 100644 dotnet-desktop-guide/net/wpf/events/how-to-create-a-custom-routed-event.md create mode 100644 dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/WpfControlLibraryCsharp/CustomButton.cs create mode 100644 dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/WpfControlLibraryCsharp/WpfControlLibrary.csproj create mode 100644 dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/WpfControlLibraryVb/CustomButton.vb create mode 100644 dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/WpfControlLibraryVb/WpfControlLibraryVb.vbproj create mode 100644 dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/csharp/App.xaml.cs create mode 100644 dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/csharp/AssemblyInfo.cs create mode 100644 dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/csharp/CodeSample.csproj create mode 100644 dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/csharp/MainWindow.xaml create mode 100644 dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/csharp/MainWindow.xaml.cs create mode 100644 dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/csharp/Properties/Resources.Designer.cs create mode 100644 dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/csharp/Properties/Resources.resx create mode 100644 dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/csharp/WpfControlLibrary.dll create mode 100644 dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/csharp/app.xaml create mode 100644 dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/vb/Application.xaml create mode 100644 dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/vb/Application.xaml.vb create mode 100644 dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/vb/AssemblyInfo.vb create mode 100644 dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/vb/CodeSampleVb.vbproj create mode 100644 dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/vb/MainWindow.xaml create mode 100644 dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/vb/MainWindow.xaml.vb create mode 100644 dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/vb/WpfControlLibraryVb.dll diff --git a/.openpublishing.redirection.json b/.openpublishing.redirection.json index a208fdb..e1b7256 100644 --- a/.openpublishing.redirection.json +++ b/.openpublishing.redirection.json @@ -612,6 +612,14 @@ { "source_path": "dotnet-desktop-guide/framework/wpf/events/how-to-add-an-event-handler-using-code.md", "redirect_url": "/dotnet/desktop/wpf/advanced/how-to-add-an-event-handler-using-code?view=netframeworkdesktop-4.8" + }, + { + "source_path": "dotnet-desktop-guide/net/wpf/advanced/how-to-create-a-custom-routed-event.md", + "redirect_url": "/dotnet/desktop/wpf/events/how-to-create-a-custom-routed-event?view=netdesktop-6.0" + }, + { + "source_path": "dotnet-desktop-guide/framework/wpf/events/how-to-create-a-custom-routed-event.md", + "redirect_url": "/dotnet/desktop/wpf/advanced/how-to-create-a-custom-routed-event?view=netframeworkdesktop-4.8" } ] } diff --git a/dotnet-desktop-guide/net/wpf/events/how-to-create-a-custom-routed-event.md b/dotnet-desktop-guide/net/wpf/events/how-to-create-a-custom-routed-event.md new file mode 100644 index 0000000..ffb013f --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/events/how-to-create-a-custom-routed-event.md @@ -0,0 +1,82 @@ +--- +title: "How to create a custom routed event" +description: Learn how to implement a custom routed event for an element in Windows Presentation Foundation (WPF). +ms.date: "02/02/2022" +dev_langs: + - "csharp" + - "vb" +helpviewer_keywords: + - "routed events [WPF], creating" + - "events [WPF], routing" +--- + + +# How to create a custom routed event (WPF .NET) + +Windows Presentation Foundation (WPF) application developers and component authors can create custom routed events to extend the functionality of common language runtime (CLR) events. For information on routed event capabilities, see [Why use routed events](/dotnet/desktop/wpf/advanced/routed-events-overview?view=netframeworkdesktop-4.8&preserve-view=true#why-use-routed-events). This article covers the basics of creating a custom routed event. + +[!INCLUDE [desktop guide under construction](../../includes/desktop-guide-preview-note.md)] + +## Routed event steps + +The basic steps to create a routed event are: + +1. Register a using the method. + +1. The registration call returns a `RoutedEvent` instance, known as a routed event identifier, which holds the registered event name, [routing strategy](/dotnet/desktop/wpf/advanced/routed-events-overview?view=netframeworkdesktop-4.8&preserve-view=true#routing-strategies), and other event details. Assign the identifier to a static readonly field. By convention: + - The identifier for a routed event with a [bubbling]() strategy is named `Event`. For example, if the event name is `Tap` then the identifier should be named `TapEvent`. + - The identifier for a routed event with a [tunneling]() strategy is named `PreviewEvent`. For example, if the event name is `Tap` then the identifier should be named `PreviewTapEvent`. + +1. Define CLR [add]() and [remove]() event accessors. Without CLR event accessors, you'll only be able to add or remove event handlers through direct calls to the and methods. With CLR event accessors, you gain these event handler assignment mechanisms: + + - For Extensible Application Markup Language (XAML), you can use attribute syntax to add event handlers. + - For C#, you can use the `+=` and `-=` operators to add or remove event handlers. + - For VB, you can use the [AddHandler](/dotnet/visual-basic/language-reference/statements/addhandler-statement) and [RemoveHandler](/dotnet/visual-basic/language-reference/statements/removehandler-statement) statements to add or remove event handlers. + +1. Add custom logic for triggering your routed event. For example, your logic might trigger the event based on user-input and application state. + +## Example + +The following example implements the `CustomButton` class in a custom control library. The `CustomButton` class, which derives from : + +1. Registers a named `ConditionalClick` using the method, and specifies the [bubbling]() strategy during registration. +1. Assigns the `RoutedEvent` instance returned from the registration call to a static readonly field named `ConditionalClickEvent`. +1. Defines CLR [add]() and [remove]() event accessors. +1. Adds custom logic to raise the custom routed event when the `CustomButton` is clicked and an external condition applies. Although the example code raises the `ConditionalClick` routed event from within the overridden `OnClick` virtual method, you can raise your event any way you choose. + +:::code language="csharp" source="./snippets/how-to-create-a-custom-routed-event/WpfControlLibraryCsharp/CustomButton.cs" id="CustomButton"::: +:::code language="vb" source="./snippets/how-to-create-a-custom-routed-event/WpfControlLibraryVb/CustomButton.vb" id="CustomButton"::: + +The example includes a separate WPF application that uses XAML markup to add an instance of the `CustomButton` to a , and to assign the `Handler_ConditionalClick` method as the `ConditionalClick` event handler for the `CustomButton` and `StackPanel1` elements. + +:::code language="xaml" source="./snippets/how-to-create-a-custom-routed-event/csharp/MainWindow.xaml" id="MainWindowXaml"::: + +In code-behind, the WPF application defines the `Handler_ConditionalClick` event handler method. Event handler methods can only be implemented in code-behind. + +:::code language="csharp" source="./snippets/how-to-create-a-custom-routed-event/csharp/MainWindow.xaml.cs" id="EventHandler"::: +:::code language="vb" source="./snippets/how-to-create-a-custom-routed-event/vb/MainWindow.xaml.vb" id="EventHandler"::: + +When `CustomButton` is clicked: + +1. The `ConditionalClick` routed event is raised on `CustomButton`. +1. The `Handler_ConditionalClick` event handler assigned to `CustomButton` is triggered. +1. The `ConditionalClick` routed event traverses up the element tree to `StackPanel1`. +1. The `Handler_ConditionalClick` event handler assigned to `StackPanel1` is triggered. +1. The `ConditionalClick` routed event continues up the element tree potentially triggering other `ConditionalClick` event handlers assigned to other traversed elements. + +The `Handler_ConditionalClick` event handler obtains the following information about the event that triggered it: + +- The [sender](xref:System.Windows.RoutedEventHandler) object, which is the element that the event handler is assigned to. The `sender` will be `CustomButton` the first time the handler runs, and `StackPanel1` the second time. +- The object, which is the element that originally raised the event. In this example, the `Source` is always `CustomButton`. + +> [!NOTE] +> A key difference between a routed event and a CLR event is that a routed event traverses the element tree, looking for handlers, whereas a CLR event is created by a source object and handled by an event subscriber. As a result, a routed event `sender` can be any traversed element in the element tree. + +You can create a tunneling event the same way as a bubbling event, except you'll set the routing strategy in the event registration call to . For more information on tunneling events, see [WPF input events](/dotnet/desktop/wpf/advanced/routed-events-overview?view=netframeworkdesktop-4.8&preserve-view=true#wpf-input-events). + +## See also + +- [Routed events overview](/dotnet/desktop/wpf/advanced/routed-events-overview?view=netframeworkdesktop-4.8&preserve-view=true) +- [Input overview](/dotnet/desktop/wpf/advanced/input-overview?view=netframeworkdesktop-4.8&preserve-view=true) +- [Control authoring overview](/dotnet/desktop/wpf/controls/control-authoring-overview?view=netframeworkdesktop-4.8&preserve-view=true) +- [Handle a routed event](/dotnet/desktop/wpf/advanced/how-to-handle-a-routed-event?view=netframeworkdesktop-4.8&preserve-view=true). diff --git a/dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/WpfControlLibraryCsharp/CustomButton.cs b/dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/WpfControlLibraryCsharp/CustomButton.cs new file mode 100644 index 0000000..8a9970e --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/WpfControlLibraryCsharp/CustomButton.cs @@ -0,0 +1,45 @@ +using System; +using System.Windows; +using System.Windows.Controls; + +namespace WpfControl +{ + // + public class CustomButton : Button + { + // Register a custom routed event using the Bubble routing strategy. + public static readonly RoutedEvent ConditionalClickEvent = EventManager.RegisterRoutedEvent( + name: "ConditionalClick", + routingStrategy: RoutingStrategy.Bubble, + handlerType: typeof(RoutedEventHandler), + ownerType: typeof(CustomButton)); + + // Provide CLR accessors for assigning an event handler. + public event RoutedEventHandler ConditionalClick + { + add { AddHandler(ConditionalClickEvent, value); } + remove { RemoveHandler(ConditionalClickEvent, value); } + } + + void RaiseCustomRoutedEvent() + { + // Create a RoutedEventArgs instance. + RoutedEventArgs routedEventArgs = new(routedEvent: ConditionalClickEvent); + + // Raise the event, which will bubble up through the element tree. + RaiseEvent(routedEventArgs); + } + + // For demo purposes, we use the Click event as a trigger. + protected override void OnClick() + { + // Some condition combined with the Click event will trigger the ConditionalClick event. + if (DateTime.Now > new DateTime()) + RaiseCustomRoutedEvent(); + + // Call the base class OnClick() method so Click event subscribers are notified. + base.OnClick(); + } + } + // +} diff --git a/dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/WpfControlLibraryCsharp/WpfControlLibrary.csproj b/dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/WpfControlLibraryCsharp/WpfControlLibrary.csproj new file mode 100644 index 0000000..9a7c06f --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/WpfControlLibraryCsharp/WpfControlLibrary.csproj @@ -0,0 +1,9 @@ + + + + net6.0-windows + enable + true + + + diff --git a/dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/WpfControlLibraryVb/CustomButton.vb b/dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/WpfControlLibraryVb/CustomButton.vb new file mode 100644 index 0000000..b68fec5 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/WpfControlLibraryVb/CustomButton.vb @@ -0,0 +1,53 @@ +Imports System.Windows +Imports System.Windows.Controls + +' +Public Class CustomButton + Inherits Button + + ' Register a custom routed event with the Bubble routing strategy. + Public Shared ReadOnly ConditionalClickEvent As RoutedEvent = EventManager.RegisterRoutedEvent( + name:="ConditionalClick", + routingStrategy:=RoutingStrategy.Bubble, + handlerType:=GetType(RoutedEventHandler), + ownerType:=GetType(CustomButton)) + + ' Provide CLR accessors to support event handler assignment. + Public Custom Event ConditionalClick As RoutedEventHandler + + AddHandler(value As RoutedEventHandler) + [AddHandler](ConditionalClickEvent, value) + End AddHandler + + RemoveHandler(value As RoutedEventHandler) + [RemoveHandler](ConditionalClickEvent, value) + End RemoveHandler + + RaiseEvent(sender As Object, e As RoutedEventArgs) + [RaiseEvent](e) + End RaiseEvent + + End Event + + Private Sub RaiseCustomRoutedEvent() + + ' Create a RoutedEventArgs instance. + Dim routedEventArgs As New RoutedEventArgs(routedEvent:=ConditionalClickEvent) + + ' Raise the event, which will bubble up through the element tree. + [RaiseEvent](routedEventArgs) + + End Sub + + ' For demo purposes, we use the Click event as a trigger. + Protected Overrides Sub OnClick() + + ' Some condition combined with the Click event will trigger the ConditionalClick event. + If Date.Now > New DateTime() Then RaiseCustomRoutedEvent() + + ' Call the base class OnClick() method so Click event subscribers are notified. + MyBase.OnClick() + + End Sub +End Class +' diff --git a/dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/WpfControlLibraryVb/WpfControlLibraryVb.vbproj b/dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/WpfControlLibraryVb/WpfControlLibraryVb.vbproj new file mode 100644 index 0000000..9bbebf2 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/WpfControlLibraryVb/WpfControlLibraryVb.vbproj @@ -0,0 +1,10 @@ + + + + WpfControlVb + WpfControlLibraryVb + net6.0-windows + true + + + diff --git a/dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/csharp/App.xaml.cs b/dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/csharp/App.xaml.cs new file mode 100644 index 0000000..93d2675 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/csharp/App.xaml.cs @@ -0,0 +1,11 @@ +using System.Windows; + +namespace CodeSample +{ + /// + /// Interaction logic for App.xaml + /// + public partial class App : Application + { + } +} diff --git a/dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/csharp/AssemblyInfo.cs b/dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/csharp/AssemblyInfo.cs new file mode 100644 index 0000000..8b5504e --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/csharp/AssemblyInfo.cs @@ -0,0 +1,10 @@ +using System.Windows; + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] diff --git a/dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/csharp/CodeSample.csproj b/dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/csharp/CodeSample.csproj new file mode 100644 index 0000000..03ce4bf --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/csharp/CodeSample.csproj @@ -0,0 +1,29 @@ + + + + WinExe + net6.0-windows + true + en-us + + + + + + + + + True + True + Resources.resx + + + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + diff --git a/dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/csharp/MainWindow.xaml b/dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/csharp/MainWindow.xaml new file mode 100644 index 0000000..546bd3a --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/csharp/MainWindow.xaml @@ -0,0 +1,17 @@ + + + + + + + + + diff --git a/dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/csharp/MainWindow.xaml.cs b/dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/csharp/MainWindow.xaml.cs new file mode 100644 index 0000000..75ba8c5 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/csharp/MainWindow.xaml.cs @@ -0,0 +1,42 @@ +using System.Diagnostics; +using System.Windows; + +namespace CodeSample +{ + public partial class MainWindow : Window + { + public MainWindow() + { + InitializeComponent(); + + // Assign an event handler to the CustomButton using the '+=' operator. + // customButton.ConditionalClick += Handler_ConditionalClick; + + // Assign an event handler to the CustomButton using the AddHandler method. + // customButton.AddHandler(WpfControl.CustomButton.ConditionalClickEvent, + // new RoutedEventHandler(Handler_ConditionalClick)); + + // Assign an event handler to the StackPanel using the AddHandler method. + // StackPanel1.AddHandler(WpfControl.CustomButton.ConditionalClickEvent, + // new RoutedEventHandler(Handler_ConditionalClick)); + } + + // + // The ConditionalClick event handler. + private void Handler_ConditionalClick(object sender, RoutedEventArgs e) + { + string senderName = ((FrameworkElement)sender).Name; + string sourceName = ((FrameworkElement)e.Source).Name; + + Debug.WriteLine($"Routed event handler attached to {senderName}, " + + $"triggered by the ConditionalClick routed event raised on {sourceName}."); + } + + // Debug output when CustomButton is clicked: + // Routed event handler attached to CustomButton, + // triggered by the ConditionalClick routed event raised on CustomButton. + // Routed event handler attached to StackPanel1, + // triggered by the ConditionalClick routed event raised on CustomButton. + // + } +} diff --git a/dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/csharp/Properties/Resources.Designer.cs b/dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/csharp/Properties/Resources.Designer.cs new file mode 100644 index 0000000..1960974 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/csharp/Properties/Resources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace CodeSample.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("CodeSample.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/csharp/Properties/Resources.resx b/dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/csharp/Properties/Resources.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/csharp/Properties/Resources.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/csharp/WpfControlLibrary.dll b/dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/csharp/WpfControlLibrary.dll new file mode 100644 index 0000000000000000000000000000000000000000..6efd2e27a673e49a7c6e480f216348f39b1cf427 GIT binary patch literal 5632 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 + + + + diff --git a/dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/vb/Application.xaml b/dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/vb/Application.xaml new file mode 100644 index 0000000..f225972 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/vb/Application.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/vb/Application.xaml.vb b/dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/vb/Application.xaml.vb new file mode 100644 index 0000000..084cbe9 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/vb/Application.xaml.vb @@ -0,0 +1,6 @@ +Class Application + + ' Application-level events, such as Startup, Exit, and DispatcherUnhandledException + ' can be handled in this file. + +End Class diff --git a/dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/vb/AssemblyInfo.vb b/dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/vb/AssemblyInfo.vb new file mode 100644 index 0000000..07b608b --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/vb/AssemblyInfo.vb @@ -0,0 +1,9 @@ +'The ThemeInfo attribute describes where any theme specific and generic resource dictionaries can be found. +'1st parameter: where theme specific resource dictionaries are located +'(used if a resource is not found in the page, +' or application resource dictionaries) + +'2nd parameter: where the generic resource dictionary is located +'(used if a resource is not found in the page, +'app, and any theme specific resource dictionaries) + diff --git a/dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/vb/CodeSampleVb.vbproj b/dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/vb/CodeSampleVb.vbproj new file mode 100644 index 0000000..396bd25 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/vb/CodeSampleVb.vbproj @@ -0,0 +1,27 @@ + + + + WinExe + net6.0-windows + CodeSampleVb + en-us + true + + + + + + + + + + + + + + + + + + + diff --git a/dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/vb/MainWindow.xaml b/dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/vb/MainWindow.xaml new file mode 100644 index 0000000..cab564b --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/vb/MainWindow.xaml @@ -0,0 +1,17 @@ + + + + + + + + + diff --git a/dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/vb/MainWindow.xaml.vb b/dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/vb/MainWindow.xaml.vb new file mode 100644 index 0000000..a76a6a3 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/vb/MainWindow.xaml.vb @@ -0,0 +1,39 @@ +Namespace CodeSampleVb + Partial Public Class MainWindow + Inherits Window + + Public Sub New() + InitializeComponent() + + ' Assign an event handler to CustomButton using the AddHandler statement. + ' AddHandler customButton.ConditionalClick, AddressOf Handler_ConditionalClick + + ' Assign an event handler to CustomButton using the AddHandler method. + ' customButton.[AddHandler](WpfControlVb.CustomButton.ConditionalClickEvent, + ' New RoutedEventHandler(AddressOf Handler_ConditionalClick)) + + ' Assign an event handler to StackPanel1 using the AddHandler method. + ' StackPanel1.[AddHandler](WpfControlVb.CustomButton.ConditionalClickEvent, + ' New RoutedEventHandler(AddressOf Handler_ConditionalClick)) + End Sub + + ' + ' The ConditionalClick event handler. + Private Sub Handler_ConditionalClick(sender As Object, e As RoutedEventArgs) + + Dim sourceName As String = CType(e.Source, FrameworkElement).Name + Dim senderName As String = CType(sender, FrameworkElement).Name + + Debug.WriteLine($"Routed event handler attached to {senderName}, " + + $"triggered by the ConditionalClick routed event raised on {sourceName}.") + + End Sub + + ' Debug output when CustomButton is clicked: + ' Routed event handler attached to CustomButton, + ' triggered by the ConditionalClick routed event raised on CustomButton. + ' Routed event handler attached to StackPanel1, + ' triggered by the ConditionalClick routed event raised on CustomButton. + ' + End Class +End Namespace diff --git a/dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/vb/WpfControlLibraryVb.dll b/dotnet-desktop-guide/net/wpf/events/snippets/how-to-create-a-custom-routed-event/vb/WpfControlLibraryVb.dll new file mode 100644 index 0000000000000000000000000000000000000000..4f83c9ff42fab46e50505ed414b29b504b075107 GIT binary patch literal 5120 zcmeHKYiJzT6+Sa7tv0K8?OoZ9OoO|s9J;ZsWmVa#A5pB;!?s*K*4nk?HVV@0?$v7S z*_r9gtYoF&Dv(eDA$>p+LZLJ%lop(lLP?#Z4+5qX;uKR_sDG4%{>YzFLi;Z*wfo&O zv)a|8A?c42O7HGH_nyZ+_ndRjoVhdcrEgG(h+5F^-X*$@QMN&b9}d>Qj(z&|82#j) zx4W(@<8OBrmUK61J66Tfs>zaOnwFO=ilkFBle(E4naU@tR#~KX?1&x+ROd#C#+4Ag z@zk{+)pvWBK9g)$azyun685QyLl~3jgXl!Nc&_?(OM zhT#fRKR$TQ!AkqSTRWj5wSy>n3x=pXOTp~u8rUrd_p2!gL=Qep>QzYyrEo-1YQp1; zA0)LU1uwvYDIFP=_F%+{IPp5S1H7mj-Y6qwv1^=CyTMKkbnhKC8a~{n zrjS=*7`8W1K9oN z;|6OzJ*156*nWK^dPJ2p>5;B{poZxUhR@J@>Q34R(J;M6?akFaex>FBzaGkk!ZaUp)flCCK1D9%D+~_-#^}2&c>~-SEwap$ zpi9eq`(%U_#O7%=O2>KLPu~wMQZ6ZF;+^lPmq1-+EZlh;+7-I$W04OO6WB8W_JC?4 zhTmaKiNsV75xM4LWW&x@y2aQHbpTpgNm_6lM%3X8uu7#rBL24#yEtGNvA+$w9t7M) zy$p{t%rYEfc%I=G8EOo5hA+|pa`VUZwb1?aWl+NOCcUht0IxIrb|^#N1pOqvKtBte z0W@eFlG3^~wbNGsJLn0(Pto@PyXhL>A^HRHB!!hU4O0i;7nq)B_z3L>r3Bbd zS@;5fTvLvnMTc^h!zCGBFBE4q~i8u8m(qM-}Q!PmUI3?a12p;UKFA zmiyCqO&4Oj*K=@0cWpykokWqKPK7!eHLg+CD5_8^7aqK&u|+Q~4*20-0Xic@I~9rs zNBw!p^4qCD|L|Q>CUUa8zJ-1hcg&meJ{UA|sd=6+cL5WFykj)C>HJ8( z_b;a&+V|MS^;xN7_{7|_uq}74YYQvPiAb4U9r@a9BU;0+?SV7LEZM>JuaykSKD`d)B*Y%dj#|-p2(CF81X;?3Ak(u=__wR(fjGV`^ewA-{^3nE9<2_;E zN0h=HQ-P-f(e&RJ7Cc#Hk1Di;U5Fphi@fhtK$p>%()Bn<%#Y;9-QPc#9Q0bSsfJj3 z|IxW*a3@v}on}3oquGchz6Uw(S;X3f?^T?w0k4xd<&7uMSR>Ej6Vj6Yx8?4WpAdWg KZ^nN$0{;R`JxYlH literal 0 HcmV?d00001 diff --git a/dotnet-desktop-guide/net/wpf/toc.yml b/dotnet-desktop-guide/net/wpf/toc.yml index d6e19dc..26bb8d7 100644 --- a/dotnet-desktop-guide/net/wpf/toc.yml +++ b/dotnet-desktop-guide/net/wpf/toc.yml @@ -84,6 +84,8 @@ items: items: - name: Add an event handler using code href: events/how-to-add-an-event-handler-using-code.md + - name: Create a custom routed event + href: events/how-to-create-a-custom-routed-event.md - name: Properties items: - name: Dependency properties diff --git a/redirects_generator/definitions.json b/redirects_generator/definitions.json index 031c6aa..ef2d8b7 100644 --- a/redirects_generator/definitions.json +++ b/redirects_generator/definitions.json @@ -333,6 +333,11 @@ "SourceUrl": "/dotnet/desktop/wpf/advanced/how-to-add-an-event-handler-using-code?view=netframeworkdesktop-4.8", "TargetUrl": "/dotnet/desktop/wpf/events/how-to-add-an-event-handler-using-code?view=netdesktop-6.0" }, + { + "Redirect": "TwoWay", + "SourceUrl": "/dotnet/desktop/wpf/advanced/how-to-create-a-custom-routed-event?view=netframeworkdesktop-4.8", + "TargetUrl": "/dotnet/desktop/wpf/events/how-to-create-a-custom-routed-event?view=netdesktop-6.0" + }, // Systems - Properties {