diff --git a/.openpublishing.redirection.json b/.openpublishing.redirection.json index e1b7256..74ff216 100644 --- a/.openpublishing.redirection.json +++ b/.openpublishing.redirection.json @@ -620,6 +620,14 @@ { "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" + }, + { + "source_path": "dotnet-desktop-guide/net/wpf/advanced/visual-basic-and-wpf-event-handling.md", + "redirect_url": "/dotnet/desktop/wpf/events/visual-basic-and-wpf-event-handling?view=netdesktop-6.0" + }, + { + "source_path": "dotnet-desktop-guide/framework/wpf/events/visual-basic-and-wpf-event-handling.md", + "redirect_url": "/dotnet/desktop/wpf/advanced/visual-basic-and-wpf-event-handling?view=netframeworkdesktop-4.8" } ] } diff --git a/dotnet-desktop-guide/net/wpf/events/how-to-add-an-event-handler-using-code.md b/dotnet-desktop-guide/net/wpf/events/how-to-add-an-event-handler-using-code.md index 4bc9094..1940b86 100644 --- a/dotnet-desktop-guide/net/wpf/events/how-to-add-an-event-handler-using-code.md +++ b/dotnet-desktop-guide/net/wpf/events/how-to-add-an-event-handler-using-code.md @@ -66,7 +66,7 @@ The `ButtonCreatedByCode_Click` event handler obtains the following information - The object, which is the element that originally raised the event. In this example, the `Source` is always `ButtonCreatedByCode`. > [!NOTE] -> A key difference between a routed event and a CLR event is that a routed event traverses the element tree, whereas a CLR event occurs only on the `sender`. As a result, a routed event `sender` can be any traversed element in the element tree. +> 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 doesn't traverse the element tree and handlers can only attach to the source object that raised the event. As a result, a routed event `sender` can be any traversed element in the element tree. For more information on how to create and handle routed events, see [How to create a custom routed event](/dotnet/desktop/wpf/advanced/how-to-create-a-custom-routed-event?view=netframeworkdesktop-4.8&preserve-view=true) and [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/visual-basic-and-wpf-event-handling/vb/Application.xaml b/dotnet-desktop-guide/net/wpf/events/snippets/visual-basic-and-wpf-event-handling/vb/Application.xaml new file mode 100644 index 0000000..f225972 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/events/snippets/visual-basic-and-wpf-event-handling/vb/Application.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/dotnet-desktop-guide/net/wpf/events/snippets/visual-basic-and-wpf-event-handling/vb/Application.xaml.vb b/dotnet-desktop-guide/net/wpf/events/snippets/visual-basic-and-wpf-event-handling/vb/Application.xaml.vb new file mode 100644 index 0000000..084cbe9 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/events/snippets/visual-basic-and-wpf-event-handling/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/visual-basic-and-wpf-event-handling/vb/AssemblyInfo.vb b/dotnet-desktop-guide/net/wpf/events/snippets/visual-basic-and-wpf-event-handling/vb/AssemblyInfo.vb new file mode 100644 index 0000000..025ee72 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/events/snippets/visual-basic-and-wpf-event-handling/vb/AssemblyInfo.vb @@ -0,0 +1,11 @@ +Imports System.Windows + +'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/visual-basic-and-wpf-event-handling/vb/CodeSampleVb.vbproj b/dotnet-desktop-guide/net/wpf/events/snippets/visual-basic-and-wpf-event-handling/vb/CodeSampleVb.vbproj new file mode 100644 index 0000000..90d032b --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/events/snippets/visual-basic-and-wpf-event-handling/vb/CodeSampleVb.vbproj @@ -0,0 +1,23 @@ + + + + WinExe + net6.0-windows + CodeSampleVb + en-us + true + + + + + + + + + + + + + + + diff --git a/dotnet-desktop-guide/net/wpf/events/snippets/visual-basic-and-wpf-event-handling/vb/MainWindow.xaml b/dotnet-desktop-guide/net/wpf/events/snippets/visual-basic-and-wpf-event-handling/vb/MainWindow.xaml new file mode 100644 index 0000000..859ea3c --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/events/snippets/visual-basic-and-wpf-event-handling/vb/MainWindow.xaml @@ -0,0 +1,15 @@ + + + + + + + + diff --git a/dotnet-desktop-guide/net/wpf/events/snippets/visual-basic-and-wpf-event-handling/vb/MainWindow.xaml.vb b/dotnet-desktop-guide/net/wpf/events/snippets/visual-basic-and-wpf-event-handling/vb/MainWindow.xaml.vb new file mode 100644 index 0000000..c34cf57 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/events/snippets/visual-basic-and-wpf-event-handling/vb/MainWindow.xaml.vb @@ -0,0 +1,61 @@ +Imports System.Windows.Controls.Primitives + +Namespace CodeSampleVb + + ' + ' Interaction logic for MainWindow.xaml. + ' + Partial Public Class MainWindow + Inherits Window + + Public Sub New() + + InitializeComponent() + + ' Add the new button to the StackPanel. + StackPanel1.Children.Add(CodeButton) + + ' Remove a handler. + ' RemoveHandler XamlButton.Click, AddressOf XamlButton_Click + + End Sub + + ' + ' Loaded event handler attached to the XAML page root using Handles. + Private Sub Window_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded + + ' Handler logic. + Debug.WriteLine($"Loaded event handler attached to Window using Handles.") + + End Sub + ' + + ' + ' Declare a new button using WithEvents. + Dim WithEvents CodeButton As New Button With { + .Content = "New button", + .Background = Brushes.Yellow + } + + ' Click event handler attached to CodeButton using Handles. + Private Sub CodeButton_Click(sender As Object, e As RoutedEventArgs) Handles CodeButton.Click + + ' Handler logic. + Debug.WriteLine($"Click event handler attached to CodeButton using Handles.") + + End Sub + ' + + ' + ' Click event handler attached to XamlButton using Handles. + Private Sub XamlButton_Click(sender As Object, e As RoutedEventArgs) Handles XamlButton.Click + + ' Handler logic. + Debug.WriteLine($"Click event handler attached to XamlButton using Handles.") + + End Sub + ' + + End Class + +End Namespace diff --git a/dotnet-desktop-guide/net/wpf/events/visual-basic-and-wpf-event-handling.md b/dotnet-desktop-guide/net/wpf/events/visual-basic-and-wpf-event-handling.md new file mode 100644 index 0000000..9236091 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/events/visual-basic-and-wpf-event-handling.md @@ -0,0 +1,64 @@ +--- +title: Visual Basic and WPF event handling +description: Learn how to attach handlers to Windows Presentation Foundation (WPF) routed events in Visual Basic. +ms.date: "02/25/2022" +helpviewer_keywords: + - "Visual Basic [WPF], event handlers" + - "event handlers [WPF], Visual Basic" +--- + + +# Visual Basic and WPF event handling (WPF .NET) + +If you're coding in Visual Basic .NET, you can use the language-specific [Handles](/dotnet/visual-basic/language-reference/statements/handles-clause) keyword to attach an event handler to an object. The object can be an instance in code-behind or an element in Extensible Application Markup Language (XAML). `Handles` can be used to assign event handlers for common language runtime (CLR) events or Windows Presentation Foundation (WPF) [routed events](/dotnet/desktop/wpf/advanced/routed-events-overview?view=netframeworkdesktop-4.8&preserve-view=true). However, `Handles` has some usage [limitations](#limitations) when used to attach event handlers for routed events. + +[!INCLUDE [desktop guide under construction](../../includes/desktop-guide-preview-note.md)] + +## Syntax + +The syntax for a `Sub` declaration that uses the [Handles](/dotnet/visual-basic/language-reference/statements/handles-clause) keyword is: `Sub Handles .`. That syntax designates a procedure as the event handler that will run when an event specified by `` is raised on an object specified by ``. The event must be a member of the object's class or base class. The following example shows how to attach an event handler to a XAML element using `Handles`. + +:::code language="vb" source="./snippets/visual-basic-and-wpf-event-handling/vb/MainWindow.xaml.vb" id="XamlButton_Click"::: + +To use `Handles` with an object defined in code-behind, typically you declare the object using the [WithEvents](/dotnet/visual-basic/language-reference/modifiers/withevents) keyword. For more information on `WithEvents` usage, see these [examples](/dotnet/visual-basic/language-reference/statements/handles-clause#example-1). WPF automatically declares all XAML elements using `Friend WithEvents`. The following example shows how to declare an object defined in code-behind using `WithEvents`. + +:::code language="vb" source="./snippets/visual-basic-and-wpf-event-handling/vb/MainWindow.xaml.vb" id="CodeButton_Click"::: + +To use the same handler for multiple events, comma-separate the `.` events. For example, `Sub Button_Click(sender As Object, e As RoutedEventArgs) Handles Button1.Click, Button2.Click`. The order of the comma-separated events is immaterial. + +You can assign different handlers for the same event with multiple `Handles` statements. The order of the `Handles` statements doesn't determine the order in which handlers are invoked when the event occurs. + +> [!TIP] +> To remove a handler that was added with `Handles`, call [RemoveHandler](/dotnet/visual-basic/language-reference/statements/removehandler-statement). For example, `RemoveHandler Button1.Click, AddressOf Button1_Click`. + +## Using 'Handles' in a WPF application + +For an object defined in XAML, the [Handles](/dotnet/visual-basic/language-reference/statements/handles-clause) event syntax `.` requires the XAML element that represents the object to have a or [x:Name](/dotnet/desktop/xaml-services/xname-directive) property. However, a name property isn't required for the XAML page root element, for which you can use the name `Me`. The following example shows how to attach an event handler to an XAML page root using `Handles`. + +:::code language="vb" source="./snippets/visual-basic-and-wpf-event-handling/vb/MainWindow.xaml.vb" id="Window_Loaded"::: + +When a XAML page is compiled, every XAML element with a `Name` or `x:Name` parameter is declared as `Friend WithEvents`. As a result, you can use any XAML element with `Handles`. + +> [!TIP] +> Visual Studio IntelliSense shows the objects that can be used with `Handles`. + +Regardless whether you attach an event handler using `Handles`, XAML attribute syntax, the [AddHandler](/dotnet/visual-basic/language-reference/statements/addhandler-statement) statement, or the method, the event system behavior is the same. + +> [!NOTE] +> Don't use both XAML attributes and `Handles` to attach the same event handler to the same event, otherwise the event handler will get called twice for each event. + +## Limitations + +The [Handles](/dotnet/visual-basic/language-reference/statements/handles-clause) keyword has these usage limitations: + +- You can only use `Handles` to attach an event handler to an object if the event is a member of the object's class or base class. For example, you can use `Handles` to attach a event handler to a button whose base class raises the `Click` routed event. However, one of the features of [routed events](/dotnet/desktop/wpf/advanced/routed-events-overview?view=netframeworkdesktop-4.8&preserve-view=true) is that they traverse the element tree, which makes it possible to listen for and handle a `Click` event at a higher level than the element that raised it. A routed event that a parent element listens for and handles is called an _attached event_. `Handles` can't be used for attached events because its syntax doesn't support specifying a different listener in the XAML element tree than the element that raised the event. To assign event handlers for attached events, you'll need to use either XAML attribute syntax or the method. For more information on attached events, see [Attached events overview](/dotnet/desktop/wpf/advanced/attached-events-overview?view=netframeworkdesktop-4.8&preserve-view=true) and [Attached events in WPF](/dotnet/desktop/wpf/advanced/routed-events-overview?view=netframeworkdesktop-4.8&preserve-view=true#attached-events-in-wpf). + +- `Handles` syntax doesn't support event handler invocation for events. To enable your event handler to be invoked for `Handled` events, attach the event handler using the method and set its `handledEventsToo` parameter to `true`. + +## See also + +- +- [Marking routed events as handled, and class handling](/dotnet/desktop/wpf/advanced/marking-routed-events-as-handled-and-class-handling?view=netframeworkdesktop-4.8&preserve-view=true) +- [Routed events overview](/dotnet/desktop/wpf/advanced/routed-events-overview?view=netframeworkdesktop-4.8&preserve-view=true) +- [Attached events overview](/dotnet/desktop/wpf/advanced/attached-events-overview?view=netframeworkdesktop-4.8&preserve-view=true) +- [XAML in WPF](/dotnet/desktop/wpf/advanced/xaml/index?view=netframeworkdesktop-4.8&preserve-view=true) diff --git a/dotnet-desktop-guide/net/wpf/toc.yml b/dotnet-desktop-guide/net/wpf/toc.yml index 26bb8d7..40579a1 100644 --- a/dotnet-desktop-guide/net/wpf/toc.yml +++ b/dotnet-desktop-guide/net/wpf/toc.yml @@ -80,6 +80,8 @@ items: items: - name: Events items: + - name: Visual Basic and WPF event handling + href: events/visual-basic-and-wpf-event-handling.md - name: Common tasks items: - name: Add an event handler using code diff --git a/redirects_generator/definitions.json b/redirects_generator/definitions.json index ef2d8b7..d143353 100644 --- a/redirects_generator/definitions.json +++ b/redirects_generator/definitions.json @@ -338,6 +338,11 @@ "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" }, + { + "Redirect": "TwoWay", + "SourceUrl": "/dotnet/desktop/wpf/advanced/visual-basic-and-wpf-event-handling?view=netframeworkdesktop-4.8", + "TargetUrl": "/dotnet/desktop/wpf/events/visual-basic-and-wpf-event-handling?view=netdesktop-6.0" + }, // Systems - Properties {