From 32aaa7e2da4a39a3f631fe987a311444a7a6ec82 Mon Sep 17 00:00:00 2001 From: v-trisshores <86677757+v-trisshores@users.noreply.github.com> Date: Wed, 22 Dec 2021 12:51:53 -0600 Subject: [PATCH 1/2] Add article, toc, and redirects --- .openpublishing.redirection.json | 8 ++ .../csharp/MainWindow.xaml.cs | 23 +++- .../vb/MainWindow.xaml.vb | 16 ++- .../csharp/App.xaml.cs | 17 +++ .../csharp/AssemblyInfo.cs | 10 ++ .../csharp/CodeSampleCsharp.csproj | 25 ++++ .../csharp/MainWindow.xaml | 5 + .../csharp/MainWindow.xaml.cs | 58 +++++++++ .../csharp/Properties/Resources.Designer.cs | 63 +++++++++ .../csharp/Properties/Resources.resx | 120 ++++++++++++++++++ .../csharp/app.xaml | 9 ++ .../vb/Application.xaml | 9 ++ .../vb/Application.xaml.vb | 6 + .../vb/AssemblyInfo.vb | 11 ++ .../vb/CodeSampleVb.vbproj | 22 ++++ .../vb/MainWindow.xaml | 5 + .../vb/MainWindow.xaml.vb | 59 +++++++++ .../xaml-loading-and-dependency-properties.md | 56 ++++++++ dotnet-desktop-guide/net/wpf/toc.yml | 2 + redirects_generator/definitions.json | 4 + 20 files changed, 519 insertions(+), 9 deletions(-) create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/xaml-loading-and-dependency-properties/csharp/App.xaml.cs create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/xaml-loading-and-dependency-properties/csharp/AssemblyInfo.cs create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/xaml-loading-and-dependency-properties/csharp/CodeSampleCsharp.csproj create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/xaml-loading-and-dependency-properties/csharp/MainWindow.xaml create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/xaml-loading-and-dependency-properties/csharp/MainWindow.xaml.cs create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/xaml-loading-and-dependency-properties/csharp/Properties/Resources.Designer.cs create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/xaml-loading-and-dependency-properties/csharp/Properties/Resources.resx create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/xaml-loading-and-dependency-properties/csharp/app.xaml create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/xaml-loading-and-dependency-properties/vb/Application.xaml create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/xaml-loading-and-dependency-properties/vb/Application.xaml.vb create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/xaml-loading-and-dependency-properties/vb/AssemblyInfo.vb create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/xaml-loading-and-dependency-properties/vb/CodeSampleVb.vbproj create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/xaml-loading-and-dependency-properties/vb/MainWindow.xaml create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/xaml-loading-and-dependency-properties/vb/MainWindow.xaml.vb create mode 100644 dotnet-desktop-guide/net/wpf/properties/xaml-loading-and-dependency-properties.md diff --git a/.openpublishing.redirection.json b/.openpublishing.redirection.json index d408defd52..958fc6daf3 100644 --- a/.openpublishing.redirection.json +++ b/.openpublishing.redirection.json @@ -588,6 +588,14 @@ { "source_path": "dotnet-desktop-guide/framework/wpf/properties/safe-constructor-patterns-for-dependencyobjects.md", "redirect_url": "/dotnet/desktop/wpf/advanced/safe-constructor-patterns-for-dependencyobjects?view=netframeworkdesktop-4.8" + }, + { + "source_path": "dotnet-desktop-guide/net/wpf/advanced/xaml-loading-and-dependency-properties.md", + "redirect_url": "/dotnet/desktop/wpf/properties/xaml-loading-and-dependency-properties?view=netdesktop-6.0" + }, + { + "source_path": "dotnet-desktop-guide/framework/wpf/properties/xaml-loading-and-dependency-properties.md", + "redirect_url": "/dotnet/desktop/wpf/advanced/xaml-loading-and-dependency-properties?view=netframeworkdesktop-4.8" } ] } diff --git a/dotnet-desktop-guide/net/wpf/properties/snippets/custom-dependency-properties/csharp/MainWindow.xaml.cs b/dotnet-desktop-guide/net/wpf/properties/snippets/custom-dependency-properties/csharp/MainWindow.xaml.cs index 8ac43f851a..53804a7777 100644 --- a/dotnet-desktop-guide/net/wpf/properties/snippets/custom-dependency-properties/csharp/MainWindow.xaml.cs +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/custom-dependency-properties/csharp/MainWindow.xaml.cs @@ -1,8 +1,6 @@ using System; +using System.Diagnostics; using System.Windows; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Windows.Shapes; namespace CodeSampleCsharp { @@ -11,6 +9,19 @@ namespace CodeSampleCsharp /// public partial class MainWindow : Window { + public MainWindow() + { + InitializeComponent(); + + // Test code. + Aquarium aquarium = new(); + aquarium.AquariumGraphic = new Uri("http://www.contoso.com/aquarium-graphic-new.jpg"); + Debug.WriteLine($"Aquarium graphic: {aquarium.AquariumGraphic}"); + + // Output: + // OnUriChanged: http://www.contoso.com/aquarium-graphic-new.jpg + // Aquarium graphic: http://www.contoso.com/aquarium-graphic-new.jpg + } } public class Aquarium : DependencyObject @@ -32,7 +43,7 @@ public class Aquarium : DependencyObject ); // - // Declare a read-write property. + // Declare a read-write property wrapper. public Uri AquariumGraphic { get => (Uri)GetValue(AquariumGraphicProperty); @@ -42,8 +53,8 @@ public Uri AquariumGraphic private static void OnUriChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e) { - Shape shape = (Shape)dependencyObject; - shape.Fill = new ImageBrush(new BitmapImage((Uri)e.NewValue)); + Uri value = (Uri)dependencyObject.GetValue(AquariumGraphicProperty); + Debug.WriteLine($"OnUriChanged: {value}"); } } } diff --git a/dotnet-desktop-guide/net/wpf/properties/snippets/custom-dependency-properties/vb/MainWindow.xaml.vb b/dotnet-desktop-guide/net/wpf/properties/snippets/custom-dependency-properties/vb/MainWindow.xaml.vb index 7112b454f4..8918b603a6 100644 --- a/dotnet-desktop-guide/net/wpf/properties/snippets/custom-dependency-properties/vb/MainWindow.xaml.vb +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/custom-dependency-properties/vb/MainWindow.xaml.vb @@ -8,7 +8,17 @@ Public Sub New() InitializeComponent() + + ' Test code. + Dim aquarium As New Aquarium With { + .AquariumGraphic = New Uri("http://www.contoso.com/aquarium-graphic-new.jpg") + } + Debug.WriteLine($"Aquarium graphic: {aquarium.AquariumGraphic}") End Sub + + ' Output: + ' OnUriChanged http://www.contoso.com/aquarium-graphic-new.jpg + ' Aquarium graphic: http://www.contoso.com/aquarium-graphic-new.jpg End Class Public Class Aquarium @@ -30,7 +40,7 @@ propertyChangedCallback:=New PropertyChangedCallback(AddressOf OnUriChanged))) ' - ' Declare a read-write property. + ' Declare a read-write property wrapper. Public Property AquariumGraphic As Uri Get Return CType(GetValue(AquariumGraphicProperty), Uri) @@ -42,8 +52,8 @@ ' Private Shared Sub OnUriChanged(dependencyObject As DependencyObject, e As DependencyPropertyChangedEventArgs) - Dim shape As Shape = CType(dependencyObject, Shape) - shape.Fill = New ImageBrush(New BitmapImage(CType(e.NewValue, Uri))) + Dim value As Uri = CType(dependencyObject.GetValue(AquariumGraphicProperty), Uri) + Debug.WriteLine($"OnUriChanged: {value}") End Sub End Class diff --git a/dotnet-desktop-guide/net/wpf/properties/snippets/xaml-loading-and-dependency-properties/csharp/App.xaml.cs b/dotnet-desktop-guide/net/wpf/properties/snippets/xaml-loading-and-dependency-properties/csharp/App.xaml.cs new file mode 100644 index 0000000000..31285520b3 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/xaml-loading-and-dependency-properties/csharp/App.xaml.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Data; +using System.Linq; +using System.Threading.Tasks; +using System.Windows; + +namespace CodeSampleCsharp +{ + /// + /// Interaction logic for App.xaml + /// + public partial class App : Application + { + } +} diff --git a/dotnet-desktop-guide/net/wpf/properties/snippets/xaml-loading-and-dependency-properties/csharp/AssemblyInfo.cs b/dotnet-desktop-guide/net/wpf/properties/snippets/xaml-loading-and-dependency-properties/csharp/AssemblyInfo.cs new file mode 100644 index 0000000000..8b5504ecfb --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/xaml-loading-and-dependency-properties/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/properties/snippets/xaml-loading-and-dependency-properties/csharp/CodeSampleCsharp.csproj b/dotnet-desktop-guide/net/wpf/properties/snippets/xaml-loading-and-dependency-properties/csharp/CodeSampleCsharp.csproj new file mode 100644 index 0000000000..7cb6479eb6 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/xaml-loading-and-dependency-properties/csharp/CodeSampleCsharp.csproj @@ -0,0 +1,25 @@ + + + + WinExe + net6.0-windows + true + en-US + + + + + True + True + Resources.resx + + + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + diff --git a/dotnet-desktop-guide/net/wpf/properties/snippets/xaml-loading-and-dependency-properties/csharp/MainWindow.xaml b/dotnet-desktop-guide/net/wpf/properties/snippets/xaml-loading-and-dependency-properties/csharp/MainWindow.xaml new file mode 100644 index 0000000000..b6e798672e --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/xaml-loading-and-dependency-properties/csharp/MainWindow.xaml @@ -0,0 +1,5 @@ + + diff --git a/dotnet-desktop-guide/net/wpf/properties/snippets/xaml-loading-and-dependency-properties/csharp/MainWindow.xaml.cs b/dotnet-desktop-guide/net/wpf/properties/snippets/xaml-loading-and-dependency-properties/csharp/MainWindow.xaml.cs new file mode 100644 index 0000000000..0e69462451 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/xaml-loading-and-dependency-properties/csharp/MainWindow.xaml.cs @@ -0,0 +1,58 @@ +using System; +using System.Diagnostics; +using System.Windows; + +namespace CodeSampleCsharp +{ + /// + /// Interaction logic for MainWindow.xaml. + /// + public partial class MainWindow : Window + { + public MainWindow() + { + InitializeComponent(); + + // Test code. + Aquarium aquarium = new(); + aquarium.AquariumGraphic = new Uri("http://www.contoso.com/aquarium-graphic-new.jpg"); + Debug.WriteLine($"Aquarium graphic: {aquarium.AquariumGraphic}"); + + // Output: + // OnUriChanged: http://www.contoso.com/aquarium-graphic-new.jpg + // Aquarium graphic: http://www.contoso.com/aquarium-graphic-new.jpg + } + } + + public class Aquarium : DependencyObject + { + // + // Register a dependency property with the specified property name, + // property type, owner type, and property metadata. Store the dependency + // property identifier as a public static readonly member of the class. + public static readonly DependencyProperty AquariumGraphicProperty = + DependencyProperty.Register( + name: "AquariumGraphic", + propertyType: typeof(Uri), + ownerType: typeof(Aquarium), + typeMetadata: new FrameworkPropertyMetadata( + defaultValue: new Uri("http://www.contoso.com/aquarium-graphic.jpg"), + flags: FrameworkPropertyMetadataOptions.AffectsRender, + propertyChangedCallback: new PropertyChangedCallback(OnUriChanged)) + ); + + // Property wrapper with get & set accessors. + public Uri AquariumGraphic + { + get => (Uri)GetValue(AquariumGraphicProperty); + set => SetValue(AquariumGraphicProperty, value); + } + // + + private static void OnUriChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e) + { + Uri value = (Uri)dependencyObject.GetValue(AquariumGraphicProperty); + Debug.WriteLine($"OnUriChanged: {value}"); + } + } +} diff --git a/dotnet-desktop-guide/net/wpf/properties/snippets/xaml-loading-and-dependency-properties/csharp/Properties/Resources.Designer.cs b/dotnet-desktop-guide/net/wpf/properties/snippets/xaml-loading-and-dependency-properties/csharp/Properties/Resources.Designer.cs new file mode 100644 index 0000000000..64552f96fd --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/xaml-loading-and-dependency-properties/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 CodeSampleCsharp.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", "16.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("CodeSampleCsharp.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/properties/snippets/xaml-loading-and-dependency-properties/csharp/Properties/Resources.resx b/dotnet-desktop-guide/net/wpf/properties/snippets/xaml-loading-and-dependency-properties/csharp/Properties/Resources.resx new file mode 100644 index 0000000000..1af7de150c --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/xaml-loading-and-dependency-properties/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/properties/snippets/xaml-loading-and-dependency-properties/csharp/app.xaml b/dotnet-desktop-guide/net/wpf/properties/snippets/xaml-loading-and-dependency-properties/csharp/app.xaml new file mode 100644 index 0000000000..867d2f015f --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/xaml-loading-and-dependency-properties/csharp/app.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/dotnet-desktop-guide/net/wpf/properties/snippets/xaml-loading-and-dependency-properties/vb/Application.xaml b/dotnet-desktop-guide/net/wpf/properties/snippets/xaml-loading-and-dependency-properties/vb/Application.xaml new file mode 100644 index 0000000000..f225972592 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/xaml-loading-and-dependency-properties/vb/Application.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/dotnet-desktop-guide/net/wpf/properties/snippets/xaml-loading-and-dependency-properties/vb/Application.xaml.vb b/dotnet-desktop-guide/net/wpf/properties/snippets/xaml-loading-and-dependency-properties/vb/Application.xaml.vb new file mode 100644 index 0000000000..084cbe917e --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/xaml-loading-and-dependency-properties/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/properties/snippets/xaml-loading-and-dependency-properties/vb/AssemblyInfo.vb b/dotnet-desktop-guide/net/wpf/properties/snippets/xaml-loading-and-dependency-properties/vb/AssemblyInfo.vb new file mode 100644 index 0000000000..025ee7271e --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/xaml-loading-and-dependency-properties/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/properties/snippets/xaml-loading-and-dependency-properties/vb/CodeSampleVb.vbproj b/dotnet-desktop-guide/net/wpf/properties/snippets/xaml-loading-and-dependency-properties/vb/CodeSampleVb.vbproj new file mode 100644 index 0000000000..34db9b0460 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/xaml-loading-and-dependency-properties/vb/CodeSampleVb.vbproj @@ -0,0 +1,22 @@ + + + + WinExe + net6.0-windows + CodeSampleVb + true + + + + + + + + + + + + + + + diff --git a/dotnet-desktop-guide/net/wpf/properties/snippets/xaml-loading-and-dependency-properties/vb/MainWindow.xaml b/dotnet-desktop-guide/net/wpf/properties/snippets/xaml-loading-and-dependency-properties/vb/MainWindow.xaml new file mode 100644 index 0000000000..37a7457b77 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/xaml-loading-and-dependency-properties/vb/MainWindow.xaml @@ -0,0 +1,5 @@ + + diff --git a/dotnet-desktop-guide/net/wpf/properties/snippets/xaml-loading-and-dependency-properties/vb/MainWindow.xaml.vb b/dotnet-desktop-guide/net/wpf/properties/snippets/xaml-loading-and-dependency-properties/vb/MainWindow.xaml.vb new file mode 100644 index 0000000000..e613d763ba --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/xaml-loading-and-dependency-properties/vb/MainWindow.xaml.vb @@ -0,0 +1,59 @@ +Namespace CodeSampleVb + + ' + ' Interaction logic for MainWindow.xaml. + ' + Partial Public Class MainWindow + Inherits Window + + Public Sub New() + InitializeComponent() + + ' Test code. + Dim aquarium As New Aquarium With { + .AquariumGraphic = New Uri("http://www.contoso.com/aquarium-graphic-new.jpg") + } + Debug.WriteLine($"Aquarium graphic: {aquarium.AquariumGraphic}") + End Sub + + ' Output: + ' OnUriChanged http://www.contoso.com/aquarium-graphic-new.jpg + ' Aquarium graphic: http://www.contoso.com/aquarium-graphic-new.jpg + End Class + + Public Class Aquarium + Inherits DependencyObject + + ' + ' Register a dependency property with the specified property name, + ' property type, owner type, and property metadata. Store the dependency + ' property identifier as a public static readonly member of the class. + Public Shared ReadOnly AquariumGraphicProperty As DependencyProperty = + DependencyProperty.Register( + name:="AquariumGraphic", + propertyType:=GetType(Uri), + ownerType:=GetType(Aquarium), + typeMetadata:=New FrameworkPropertyMetadata( + defaultValue:=New Uri("http://www.contoso.com/aquarium-graphic.jpg"), + flags:=FrameworkPropertyMetadataOptions.AffectsRender, + propertyChangedCallback:=New PropertyChangedCallback(AddressOf OnUriChanged))) + + ' Property wrapper with get & set accessors. + Public Property AquariumGraphic As Uri + Get + Return CType(GetValue(AquariumGraphicProperty), Uri) + End Get + Set + SetValue(AquariumGraphicProperty, Value) + End Set + End Property + ' + + Private Shared Sub OnUriChanged(dependencyObject As DependencyObject, e As DependencyPropertyChangedEventArgs) + Dim value As Uri = CType(dependencyObject.GetValue(AquariumGraphicProperty), Uri) + Debug.WriteLine($"OnUriChanged: {value}") + End Sub + + End Class + +End Namespace diff --git a/dotnet-desktop-guide/net/wpf/properties/xaml-loading-and-dependency-properties.md b/dotnet-desktop-guide/net/wpf/properties/xaml-loading-and-dependency-properties.md new file mode 100644 index 0000000000..cd1eab6aa0 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/xaml-loading-and-dependency-properties.md @@ -0,0 +1,56 @@ +--- +title: "XAML loading and dependency properties" +description: "Learn about Extensible Application Markup Language (XAML) loading of dependency property in Windows Presentation Foundation (WPF)." +ms.date: "12/22/2021" +dev_langs: + - "csharp" + - "vb" +helpviewer_keywords: + - "custom dependency properties [WPF]" + - "dependency properties [WPF], XAML loading" + - "loading XML data [WPF]" +--- + + +# XAML loading and dependency properties (WPF .NET) + +The Windows Presentation Foundation (WPF) implementation of its Extensible Application Markup Language (XAML) processor is inherently dependency property aware. As such, the XAML processor uses WPF property system methods to load XAML and process dependency property attributes, and entirely bypasses dependency property wrappers by using WPF property system methods like and . So, if you add custom logic to the property wrapper of your custom dependency property, it won't be called by the XAML processor when a property value is set in XAML. + +[!INCLUDE [desktop guide under construction](../../includes/desktop-guide-preview-note.md)] + +## Prerequisites + +The article assumes a basic knowledge of dependency properties, and that you've read [Dependency properties overview](dependency-properties-overview.md). To follow the examples in this article, it helps if you're familiar with Extensible Application Markup Language (XAML) and know how to write WPF applications. + +## WPF XAML loader performance + +It's computationally less expensive for the WPF XAML processor to directly call to set the value of a dependency property, rather than use the property wrapper of a dependency property. + +If the XAML processor did use the property wrapper, it would require inferring the entire object model of the backing code based only on the type and member relationships indicated in markup. Although the type can be identified from markup by using a combination of `xmlns` and assembly attributes, identifying the members, determining which members can be set as an attribute, and resolving supported property value types, would require extensive reflection using . + +The WPF property system maintains a storage table of dependency properties implemented on a given derived type. The XAML processor uses that table to infer the dependency property identifier for a dependency property. For example, by convention the dependency property identifier for a dependency property named `ABC` is `ABCProperty`. The XAML processor can efficiently set the value of any dependency property by calling the `SetValue` method on its containing type using the dependency property identifier. + +For more information on dependency property wrappers, see [Custom dependency properties](custom-dependency-properties.md). + +## Implications for custom dependency properties + +The WPF XAML processor bypasses property wrappers and directly calls to set a dependency property value. So, avoid putting any extra logic in the `set` accessor of your custom dependency property because that logic won't run when a property value is set in XAML. The `set` accessor should only contain a `SetValue` call. + +Similarly, aspects of the WPF XAML processor that get property values bypass the property wrapper and directly call . So, also avoid putting any extra logic in the `get` accessor of your custom dependency property because that logic won't run when a property value is read in XAML. The `get` accessor should only contain a `GetValue` call. + +## Dependency property with wrapper example + +The following example shows a recommended dependency property definition with property wrappers. The dependency property identifier is stored as a `public static readonly` field, and the `get` and `set` accessors contain no code beyond the necessary WPF property system methods that back the dependency property value. + +:::code language="csharp" source="./snippets/xaml-loading-and-dependency-properties/csharp/MainWindow.xaml.cs" id="DependencyPropertyWithWrapper"::: +:::code language="vb" source="./snippets/xaml-loading-and-dependency-properties/vb/MainWindow.xaml.vb" id="DependencyPropertyWithWrapper"::: + +## See also + +- [Dependency properties overview](dependency-properties-overview.md) +- [XAML in WPF](/dotnet/desktop/wpf/advanced/xaml-in-wpf?view=netframeworkdesktop-4.8&preserve-view=true) +- [Custom dependency properties](custom-dependency-properties.md) +- [Dependency property metadata](dependency-property-metadata.md) +- [Collection-type dependency properties](collection-type-dependency-properties.md) +- [Dependency property security](dependency-property-security.md) +- [Safe constructor patterns for DependencyObjects](/dotnet/desktop/wpf/advanced/safe-constructor-patterns-for-dependencyobjects?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 e697dea2cc..411c7084b8 100644 --- a/dotnet-desktop-guide/net/wpf/toc.yml +++ b/dotnet-desktop-guide/net/wpf/toc.yml @@ -102,6 +102,8 @@ items: href: properties/dependency-property-security.md - name: Safe constructor patterns for DependencyObjects href: properties/safe-constructor-patterns-for-dependencyobjects.md + - name: XAML loading and dependency properties + href: properties/xaml-loading-and-dependency-properties.md - name: Common tasks items: - name: Implement a dependency property diff --git a/redirects_generator/definitions.json b/redirects_generator/definitions.json index d3f02b2625..4172523fdb 100644 --- a/redirects_generator/definitions.json +++ b/redirects_generator/definitions.json @@ -395,6 +395,10 @@ "SourceUrl": "/dotnet/desktop/wpf/advanced/safe-constructor-patterns-for-dependencyobjects?view=netframeworkdesktop-4.8", "TargetUrl": "/dotnet/desktop/wpf/properties/safe-constructor-patterns-for-dependencyobjects?view=netdesktop-6.0" }, + { + "SourceUrl": "/dotnet/desktop/wpf/advanced/xaml-loading-and-dependency-properties?view=netframeworkdesktop-4.8", + "TargetUrl": "/dotnet/desktop/wpf/properties/xaml-loading-and-dependency-properties?view=netdesktop-6.0" + }, // Systems - XAML { From 59b00384a50d214dc6c596b7937f88ca72916b70 Mon Sep 17 00:00:00 2001 From: v-trisshores <86677757+v-trisshores@users.noreply.github.com> Date: Wed, 5 Jan 2022 15:05:53 -0600 Subject: [PATCH 2/2] Add info on use of a callback to run custom logic and resolve merge conflicts --- .../csharp/MainWindow.xaml.cs | 11 +++++++---- .../vb/MainWindow.xaml.vb | 11 +++++++---- .../xaml-loading-and-dependency-properties.md | 2 +- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/dotnet-desktop-guide/net/wpf/properties/snippets/xaml-loading-and-dependency-properties/csharp/MainWindow.xaml.cs b/dotnet-desktop-guide/net/wpf/properties/snippets/xaml-loading-and-dependency-properties/csharp/MainWindow.xaml.cs index 0e69462451..43e6ad6b1b 100644 --- a/dotnet-desktop-guide/net/wpf/properties/snippets/xaml-loading-and-dependency-properties/csharp/MainWindow.xaml.cs +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/xaml-loading-and-dependency-properties/csharp/MainWindow.xaml.cs @@ -47,12 +47,15 @@ public Uri AquariumGraphic get => (Uri)GetValue(AquariumGraphicProperty); set => SetValue(AquariumGraphicProperty, value); } - // - private static void OnUriChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e) + // Property-changed callback. + private static void OnUriChanged(DependencyObject dependencyObject, + DependencyPropertyChangedEventArgs e) { - Uri value = (Uri)dependencyObject.GetValue(AquariumGraphicProperty); - Debug.WriteLine($"OnUriChanged: {value}"); + // Some custom logic that runs on effective property value change. + Uri newValue = (Uri)dependencyObject.GetValue(AquariumGraphicProperty); + Debug.WriteLine($"OnUriChanged: {newValue}"); } + // } } diff --git a/dotnet-desktop-guide/net/wpf/properties/snippets/xaml-loading-and-dependency-properties/vb/MainWindow.xaml.vb b/dotnet-desktop-guide/net/wpf/properties/snippets/xaml-loading-and-dependency-properties/vb/MainWindow.xaml.vb index e613d763ba..c508a8a430 100644 --- a/dotnet-desktop-guide/net/wpf/properties/snippets/xaml-loading-and-dependency-properties/vb/MainWindow.xaml.vb +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/xaml-loading-and-dependency-properties/vb/MainWindow.xaml.vb @@ -47,12 +47,15 @@ SetValue(AquariumGraphicProperty, Value) End Set End Property - ' - Private Shared Sub OnUriChanged(dependencyObject As DependencyObject, e As DependencyPropertyChangedEventArgs) - Dim value As Uri = CType(dependencyObject.GetValue(AquariumGraphicProperty), Uri) - Debug.WriteLine($"OnUriChanged: {value}") + ' Property-changed callback. + Private Shared Sub OnUriChanged(dependencyObject As DependencyObject, + e As DependencyPropertyChangedEventArgs) + ' Some custom logic that runs on effective property value change. + Dim newValue As Uri = CType(dependencyObject.GetValue(AquariumGraphicProperty), Uri) + Debug.WriteLine($"OnUriChanged: {newValue}") End Sub + ' End Class diff --git a/dotnet-desktop-guide/net/wpf/properties/xaml-loading-and-dependency-properties.md b/dotnet-desktop-guide/net/wpf/properties/xaml-loading-and-dependency-properties.md index cd1eab6aa0..e6ab66544e 100644 --- a/dotnet-desktop-guide/net/wpf/properties/xaml-loading-and-dependency-properties.md +++ b/dotnet-desktop-guide/net/wpf/properties/xaml-loading-and-dependency-properties.md @@ -40,7 +40,7 @@ Similarly, aspects of the WPF XAML processor that get property values bypass the ## Dependency property with wrapper example -The following example shows a recommended dependency property definition with property wrappers. The dependency property identifier is stored as a `public static readonly` field, and the `get` and `set` accessors contain no code beyond the necessary WPF property system methods that back the dependency property value. +The following example shows a recommended dependency property definition with property wrappers. The dependency property identifier is stored as a `public static readonly` field, and the `get` and `set` accessors contain no code beyond the necessary WPF property system methods that back the dependency property value. If you have code that needs to run when the value of your dependency property changes, consider putting that code in the for your dependency property. For more information, see [Property-changed callbacks](/dotnet/desktop/wpf/properties/dependency-property-callbacks-and-validation?preserve-view=true#property-changed-callbacks). :::code language="csharp" source="./snippets/xaml-loading-and-dependency-properties/csharp/MainWindow.xaml.cs" id="DependencyPropertyWithWrapper"::: :::code language="vb" source="./snippets/xaml-loading-and-dependency-properties/vb/MainWindow.xaml.vb" id="DependencyPropertyWithWrapper":::