From e6a2fd1bf1941ecad69437195a3316802bead516 Mon Sep 17 00:00:00 2001 From: atulll <39869656+underager@users.noreply.github.com> Date: Thu, 21 Oct 2021 21:56:31 +0530 Subject: [PATCH 1/9] Specifying ItemsSource attribute in DataGrid element (#1183) * Specifying ItemsSource attribute in DataGrid element #### Reference issues/PRs None #### What does this implements/fix? Explain your changes? The ItemsSource attribute addition in the below code sample wasn't mentioned in the documentation. #### Any Comments None * Minor; inline code elements Co-authored-by: Andy (Steve) De George <67293991+adegeo@users.noreply.github.com> --- .../walkthrough-my-first-wpf-desktop-application.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dotnet-desktop-guide/framework/wpf/getting-started/walkthrough-my-first-wpf-desktop-application.md b/dotnet-desktop-guide/framework/wpf/getting-started/walkthrough-my-first-wpf-desktop-application.md index 8f6afc1..3f6352b 100644 --- a/dotnet-desktop-guide/framework/wpf/getting-started/walkthrough-my-first-wpf-desktop-application.md +++ b/dotnet-desktop-guide/framework/wpf/getting-started/walkthrough-my-first-wpf-desktop-application.md @@ -454,7 +454,7 @@ In this section, you'll update the UI for each item in the data-bound lists by u [!code-xaml[ExpenseIt#30](~/samples/snippets/csharp/VS_Snippets_Wpf/ExpenseIt/CSharp/ExpenseIt9/ExpenseReportPage.xaml#30)] -4. Replace the elements with under the element and apply the templates to them. +4. Replace the elements with under the element and apply the templates to them. Also, specify the `ItemsSource` attribute with its value in the `DataGrid` Element. [!code-xaml[ExpenseIt#32](~/samples/snippets/csharp/VS_Snippets_Wpf/ExpenseIt/CSharp/ExpenseIt9/ExpenseReportPage.xaml#32)] From 700f7256816e5fb4983a7964137f4c24f748b173 Mon Sep 17 00:00:00 2001 From: Tris Shores <86677757+v-trisshores@users.noreply.github.com> Date: Thu, 21 Oct 2021 13:37:58 -0500 Subject: [PATCH 2/9] Add article, code projects, toc, and redirects (#1179) --- .openpublishing.redirection.json | 8 ++ .../how-to-register-an-attached-property.md | 33 +++++ .../csharp/App.xaml.cs | 11 ++ .../csharp/AssemblyInfo.cs | 10 ++ .../csharp/CodeSampleCsharp.csproj | 24 ++++ .../csharp/MainWindow.xaml | 3 + .../csharp/MainWindow.xaml.cs | 37 ++++++ .../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 | 3 + .../vb/MainWindow.xaml.vb | 39 ++++++ dotnet-desktop-guide/net/wpf/toc.yml | 2 + redirects_generator/definitions.json | 5 + 18 files changed, 415 insertions(+) create mode 100644 dotnet-desktop-guide/net/wpf/properties/how-to-register-an-attached-property.md create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/how-to-register-an-attached-property/csharp/App.xaml.cs create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/how-to-register-an-attached-property/csharp/AssemblyInfo.cs create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/how-to-register-an-attached-property/csharp/CodeSampleCsharp.csproj create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/how-to-register-an-attached-property/csharp/MainWindow.xaml create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/how-to-register-an-attached-property/csharp/MainWindow.xaml.cs create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/how-to-register-an-attached-property/csharp/Properties/Resources.Designer.cs create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/how-to-register-an-attached-property/csharp/Properties/Resources.resx create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/how-to-register-an-attached-property/csharp/app.xaml create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/how-to-register-an-attached-property/vb/Application.xaml create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/how-to-register-an-attached-property/vb/Application.xaml.vb create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/how-to-register-an-attached-property/vb/AssemblyInfo.vb create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/how-to-register-an-attached-property/vb/CodeSampleVb.vbproj create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/how-to-register-an-attached-property/vb/MainWindow.xaml create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/how-to-register-an-attached-property/vb/MainWindow.xaml.vb diff --git a/.openpublishing.redirection.json b/.openpublishing.redirection.json index 89b3205..f71b9a8 100644 --- a/.openpublishing.redirection.json +++ b/.openpublishing.redirection.json @@ -488,6 +488,14 @@ { "source_path": "dotnet-desktop-guide/framework/wpf/properties/dependency-property-value-precedence.md", "redirect_url": "/dotnet/desktop/wpf/advanced/dependency-property-value-precedence?view=netframeworkdesktop-4.8" + }, + { + "source_path": "dotnet-desktop-guide/net/wpf/advanced/how-to-register-an-attached-property.md", + "redirect_url": "/dotnet/desktop/wpf/properties/how-to-register-an-attached-property?view=netdesktop-5.0" + }, + { + "source_path": "dotnet-desktop-guide/framework/wpf/properties/how-to-register-an-attached-property.md", + "redirect_url": "/dotnet/desktop/wpf/advanced/how-to-register-an-attached-property?view=netframeworkdesktop-4.8" } ] } diff --git a/dotnet-desktop-guide/net/wpf/properties/how-to-register-an-attached-property.md b/dotnet-desktop-guide/net/wpf/properties/how-to-register-an-attached-property.md new file mode 100644 index 0000000..94396cd --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/how-to-register-an-attached-property.md @@ -0,0 +1,33 @@ +--- +title: "How to register an attached property" +description: "Learn about the Windows Presentation Foundation (WPF) property system and how to register an attached property and provide public accessors." +ms.date: "10/15/2021" +dev_langs: + - "csharp" + - "vb" +helpviewer_keywords: + - "attached properties [WPF], registering" + - "registering attached properties [WPF]" +--- + + +# How to register an attached property (WPF .NET) + +This article describes how to register an attached property and provide public accessors that let you access the attached property through Extensible Application Markup Language (XAML) and code. Attached properties enable extra property/value pairs to be set on any XAML element, even though the element doesn't define those extra properties in its object model. The extra properties are globally accessible. Attached properties are typically defined as a specialized form of dependency property that doesn't have a conventional property wrapper. Most attached properties for Windows Presentation Foundation (WPF) types are also implemented as dependency properties. You can create dependency properties on any derived type. + +## Example + +The following example shows how to register an attached property as a dependency property, by using the method. The provider class has the option of specifying a default value in property metadata. For more information on property metadata, see [Property metadata for a new dependency property](/dotnet/desktop/wpf/advanced/custom-dependency-properties?view=netframeworkdesktop-4.8&preserve-view=true#property-metadata-for-a-new-dependency-property). In this example, the `HasFish` property has a value type, with its default value set to `false`. + +The provider class for an attached property must provide static get/set accessor methods that follow the naming convention `Get` and `Set`. The XAML reader uses the accessors to recognize the XAML attribute for the attached property and resolve its value to the appropriate type. These accessors are necessary even if an attached property isn't registered as a dependency property. + +:::code language="csharp" source="./snippets/how-to-register-an-attached-property/csharp/MainWindow.xaml.cs" id="RegisterAttachedProperty"::: +:::code language="vb" source="./snippets/how-to-register-an-attached-property/vb/MainWindow.xaml.vb" id="RegisterAttachedProperty"::: + +## See also + +- +- [Attached properties overview](/dotnet/desktop/wpf/advanced/attached-properties-overview?view=netframeworkdesktop-4.8&preserve-view=true) +- [Dependency properties overview](dependency-properties-overview.md) +- [Custom dependency properties](/dotnet/desktop/wpf/advanced/custom-dependency-properties?view=netframeworkdesktop-4.8&preserve-view=true) +- [How-to topics](/dotnet/desktop/wpf/advanced/properties-how-to-topics?view=netframeworkdesktop-4.8&preserve-view=true) diff --git a/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-register-an-attached-property/csharp/App.xaml.cs b/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-register-an-attached-property/csharp/App.xaml.cs new file mode 100644 index 0000000..bdad66d --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-register-an-attached-property/csharp/App.xaml.cs @@ -0,0 +1,11 @@ +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/how-to-register-an-attached-property/csharp/AssemblyInfo.cs b/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-register-an-attached-property/csharp/AssemblyInfo.cs new file mode 100644 index 0000000..8b5504e --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-register-an-attached-property/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/how-to-register-an-attached-property/csharp/CodeSampleCsharp.csproj b/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-register-an-attached-property/csharp/CodeSampleCsharp.csproj new file mode 100644 index 0000000..8824b2f --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-register-an-attached-property/csharp/CodeSampleCsharp.csproj @@ -0,0 +1,24 @@ + + + + WinExe + net5.0-windows + true + + + + + True + True + Resources.resx + + + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + diff --git a/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-register-an-attached-property/csharp/MainWindow.xaml b/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-register-an-attached-property/csharp/MainWindow.xaml new file mode 100644 index 0000000..744218c --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-register-an-attached-property/csharp/MainWindow.xaml @@ -0,0 +1,3 @@ + diff --git a/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-register-an-attached-property/csharp/MainWindow.xaml.cs b/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-register-an-attached-property/csharp/MainWindow.xaml.cs new file mode 100644 index 0000000..7c61da6 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-register-an-attached-property/csharp/MainWindow.xaml.cs @@ -0,0 +1,37 @@ +using System.Windows; +using System.Windows.Controls; + +namespace CodeSampleCsharp +{ + /// + /// Interaction logic for MainWindow.xaml. + /// + public partial class MainWindow : Window + { + public MainWindow() => InitializeComponent(); + } + + // + public class Aquarium : DependencyObject + { + // Register an attached dependency property with the specified + // property name, property type, owner type, and property metadata. + public static readonly DependencyProperty HasFishProperty = + DependencyProperty.RegisterAttached( + "HasFish", + typeof(bool), + typeof(Aquarium), + new FrameworkPropertyMetadata(defaultValue: false, + flags: FrameworkPropertyMetadataOptions.AffectsRender) + ); + + // Declare a get accessor method. + public static bool GetHasFish(UIElement target) => + (bool)target.GetValue(HasFishProperty); + + // Declare a set accessor method. + public static void SetHasFish(UIElement target, bool value) => + target.SetValue(HasFishProperty, value); + } + // +} diff --git a/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-register-an-attached-property/csharp/Properties/Resources.Designer.cs b/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-register-an-attached-property/csharp/Properties/Resources.Designer.cs new file mode 100644 index 0000000..64552f9 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-register-an-attached-property/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/how-to-register-an-attached-property/csharp/Properties/Resources.resx b/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-register-an-attached-property/csharp/Properties/Resources.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-register-an-attached-property/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/how-to-register-an-attached-property/csharp/app.xaml b/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-register-an-attached-property/csharp/app.xaml new file mode 100644 index 0000000..867d2f0 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-register-an-attached-property/csharp/app.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-register-an-attached-property/vb/Application.xaml b/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-register-an-attached-property/vb/Application.xaml new file mode 100644 index 0000000..f225972 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-register-an-attached-property/vb/Application.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-register-an-attached-property/vb/Application.xaml.vb b/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-register-an-attached-property/vb/Application.xaml.vb new file mode 100644 index 0000000..084cbe9 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-register-an-attached-property/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/how-to-register-an-attached-property/vb/AssemblyInfo.vb b/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-register-an-attached-property/vb/AssemblyInfo.vb new file mode 100644 index 0000000..025ee72 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-register-an-attached-property/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/how-to-register-an-attached-property/vb/CodeSampleVb.vbproj b/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-register-an-attached-property/vb/CodeSampleVb.vbproj new file mode 100644 index 0000000..c7ae1cc --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-register-an-attached-property/vb/CodeSampleVb.vbproj @@ -0,0 +1,22 @@ + + + + WinExe + net5.0-windows + CodeSampleVb + true + + + + + + + + + + + + + + + diff --git a/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-register-an-attached-property/vb/MainWindow.xaml b/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-register-an-attached-property/vb/MainWindow.xaml new file mode 100644 index 0000000..85e5cee --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-register-an-attached-property/vb/MainWindow.xaml @@ -0,0 +1,3 @@ + diff --git a/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-register-an-attached-property/vb/MainWindow.xaml.vb b/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-register-an-attached-property/vb/MainWindow.xaml.vb new file mode 100644 index 0000000..b1b3e45 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-register-an-attached-property/vb/MainWindow.xaml.vb @@ -0,0 +1,39 @@ +Namespace CodeSampleVb + + ' + ' Interaction logic for MainWindow.xaml. + ' + Partial Public Class MainWindow + Inherits Window + + Public Sub New() + InitializeComponent() + End Sub + + End Class + + ' + Public Class Aquarium + Inherits DependencyObject + + ' Register an attached dependency property with the specified + ' property name, property type, owner type, and property metadata. + Public Shared ReadOnly HasFishProperty As DependencyProperty = + DependencyProperty.RegisterAttached("HasFish", GetType(Boolean), GetType(Aquarium), + New FrameworkPropertyMetadata(defaultValue:=False, + flags:=FrameworkPropertyMetadataOptions.AffectsRender)) + + ' Declare a get accessor method. + Public Shared Function GetHasFish(target As UIElement) As Boolean + Return target.GetValue(HasFishProperty) + End Function + + ' Declare a set accessor method. + Public Shared Sub SetHasFish(target As UIElement, value As Boolean) + target.SetValue(HasFishProperty, value) + End Sub + + End Class + ' + +End Namespace diff --git a/dotnet-desktop-guide/net/wpf/toc.yml b/dotnet-desktop-guide/net/wpf/toc.yml index 15597dd..86cf216 100644 --- a/dotnet-desktop-guide/net/wpf/toc.yml +++ b/dotnet-desktop-guide/net/wpf/toc.yml @@ -84,6 +84,8 @@ items: href: properties/dependency-properties-overview.md - name: Dependency property value precedence href: properties/dependency-property-value-precedence.md + - name: Register an attached property + href: properties/how-to-register-an-attached-property.md - name: Resources items: - name: Overview diff --git a/redirects_generator/definitions.json b/redirects_generator/definitions.json index a8e4b9c..083db02 100644 --- a/redirects_generator/definitions.json +++ b/redirects_generator/definitions.json @@ -329,6 +329,11 @@ "SourceUrl": "/dotnet/desktop/wpf/advanced/dependency-property-value-precedence?view=netframeworkdesktop-4.8", "TargetUrl": "/dotnet/desktop/wpf/properties/dependency-property-value-precedence?view=netdesktop-5.0" }, + { + "Redirect": "TwoWay", + "SourceUrl": "/dotnet/desktop/wpf/advanced/how-to-register-an-attached-property?view=netframeworkdesktop-4.8", + "TargetUrl": "/dotnet/desktop/wpf/properties/how-to-register-an-attached-property?view=netdesktop-5.0" + }, // Systems - XAML { From cb4acd590a2d44b37d47bc82c850fbe0b7f65ed1 Mon Sep 17 00:00:00 2001 From: "Andy (Steve) De George" <67293991+adegeo@users.noreply.github.com> Date: Thu, 21 Oct 2021 12:35:11 -0700 Subject: [PATCH 3/9] Backport the fix to prop precedence from .NET to Framework (#1171) * Update page4.xaml * Update page4.xaml * Add snippet * Change reference --- .../dependency-property-value-precedence.md | 2 +- .../xaml/App.xaml | 9 ++ .../xaml/App.xaml.cs | 17 +++ .../xaml/AssemblyInfo.cs | 10 ++ .../xaml/CodeSampleCsharp.csproj | 24 ++++ .../xaml/MainWindow.xaml | 34 +++++ .../xaml/MainWindow.xaml.cs | 48 +++++++ .../xaml/Properties/Resources.Designer.cs | 63 +++++++++ .../xaml/Properties/Resources.resx | 120 ++++++++++++++++++ .../PropertiesOvwSupport/CSharp/page4.xaml | 45 ++++--- 10 files changed, 350 insertions(+), 22 deletions(-) create mode 100644 dotnet-desktop-guide/framework/wpf/advanced/snippets/dependency-property-value-precedence/xaml/App.xaml create mode 100644 dotnet-desktop-guide/framework/wpf/advanced/snippets/dependency-property-value-precedence/xaml/App.xaml.cs create mode 100644 dotnet-desktop-guide/framework/wpf/advanced/snippets/dependency-property-value-precedence/xaml/AssemblyInfo.cs create mode 100644 dotnet-desktop-guide/framework/wpf/advanced/snippets/dependency-property-value-precedence/xaml/CodeSampleCsharp.csproj create mode 100644 dotnet-desktop-guide/framework/wpf/advanced/snippets/dependency-property-value-precedence/xaml/MainWindow.xaml create mode 100644 dotnet-desktop-guide/framework/wpf/advanced/snippets/dependency-property-value-precedence/xaml/MainWindow.xaml.cs create mode 100644 dotnet-desktop-guide/framework/wpf/advanced/snippets/dependency-property-value-precedence/xaml/Properties/Resources.Designer.cs create mode 100644 dotnet-desktop-guide/framework/wpf/advanced/snippets/dependency-property-value-precedence/xaml/Properties/Resources.resx diff --git a/dotnet-desktop-guide/framework/wpf/advanced/dependency-property-value-precedence.md b/dotnet-desktop-guide/framework/wpf/advanced/dependency-property-value-precedence.md index 99090d6..d383be4 100644 --- a/dotnet-desktop-guide/framework/wpf/advanced/dependency-property-value-precedence.md +++ b/dotnet-desktop-guide/framework/wpf/advanced/dependency-property-value-precedence.md @@ -23,7 +23,7 @@ ms.assetid: 1fbada8e-4867-4ed1-8d97-62c07dad7ebc ## Dependency Properties Might Be "Set" in Multiple Places The following is example [!INCLUDE[TLA2#tla_xaml](../../../includes/tla2sharptla-xaml-md.md)] where the same property () has three different "set" operations that might influence the value. - [!code-xaml[PropertiesOvwSupport#DPPrecedence](~/samples/snippets/csharp/VS_Snippets_Wpf/PropertiesOvwSupport/CSharp/page4.xaml#dpprecedence)] + :::code language="xaml" source="./snippets/dependency-property-value-precedence/xaml/MainWindow.xaml" id="DependencyPropertyValuePrecedence"::: Here, which color do you expect will apply—red, green, or blue? diff --git a/dotnet-desktop-guide/framework/wpf/advanced/snippets/dependency-property-value-precedence/xaml/App.xaml b/dotnet-desktop-guide/framework/wpf/advanced/snippets/dependency-property-value-precedence/xaml/App.xaml new file mode 100644 index 0000000..867d2f0 --- /dev/null +++ b/dotnet-desktop-guide/framework/wpf/advanced/snippets/dependency-property-value-precedence/xaml/App.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/dotnet-desktop-guide/framework/wpf/advanced/snippets/dependency-property-value-precedence/xaml/App.xaml.cs b/dotnet-desktop-guide/framework/wpf/advanced/snippets/dependency-property-value-precedence/xaml/App.xaml.cs new file mode 100644 index 0000000..3128552 --- /dev/null +++ b/dotnet-desktop-guide/framework/wpf/advanced/snippets/dependency-property-value-precedence/xaml/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/framework/wpf/advanced/snippets/dependency-property-value-precedence/xaml/AssemblyInfo.cs b/dotnet-desktop-guide/framework/wpf/advanced/snippets/dependency-property-value-precedence/xaml/AssemblyInfo.cs new file mode 100644 index 0000000..8b5504e --- /dev/null +++ b/dotnet-desktop-guide/framework/wpf/advanced/snippets/dependency-property-value-precedence/xaml/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/framework/wpf/advanced/snippets/dependency-property-value-precedence/xaml/CodeSampleCsharp.csproj b/dotnet-desktop-guide/framework/wpf/advanced/snippets/dependency-property-value-precedence/xaml/CodeSampleCsharp.csproj new file mode 100644 index 0000000..8824b2f --- /dev/null +++ b/dotnet-desktop-guide/framework/wpf/advanced/snippets/dependency-property-value-precedence/xaml/CodeSampleCsharp.csproj @@ -0,0 +1,24 @@ + + + + WinExe + net5.0-windows + true + + + + + True + True + Resources.resx + + + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + diff --git a/dotnet-desktop-guide/framework/wpf/advanced/snippets/dependency-property-value-precedence/xaml/MainWindow.xaml b/dotnet-desktop-guide/framework/wpf/advanced/snippets/dependency-property-value-precedence/xaml/MainWindow.xaml new file mode 100644 index 0000000..b36725c --- /dev/null +++ b/dotnet-desktop-guide/framework/wpf/advanced/snippets/dependency-property-value-precedence/xaml/MainWindow.xaml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + diff --git a/dotnet-desktop-guide/framework/wpf/advanced/snippets/dependency-property-value-precedence/xaml/MainWindow.xaml.cs b/dotnet-desktop-guide/framework/wpf/advanced/snippets/dependency-property-value-precedence/xaml/MainWindow.xaml.cs new file mode 100644 index 0000000..1c3615d --- /dev/null +++ b/dotnet-desktop-guide/framework/wpf/advanced/snippets/dependency-property-value-precedence/xaml/MainWindow.xaml.cs @@ -0,0 +1,48 @@ +using System.Windows; +using System.Windows.Controls; + +namespace CodeSampleCsharp +{ + /// + /// Interaction logic for MainWindow.xaml. + /// + public partial class MainWindow : Window + { + public MainWindow() + { + InitializeComponent(); + + // + Button myButton = new(); + myButton.Width = 200.0; + // + + // + double whatWidth = myButton.Width; + // + } + + // + public static readonly DependencyProperty IsSpinningProperty = DependencyProperty.Register( + "IsSpinning", typeof(bool), + typeof(MainWindow) + ); + + public bool IsSpinning + { + get => (bool)GetValue(IsSpinningProperty); + set => SetValue(IsSpinningProperty, value); + } + // + } + + // + public class SpinnerControl : ItemsControl + { + static SpinnerControl() => DefaultStyleKeyProperty.OverrideMetadata( + typeof(SpinnerControl), + new FrameworkPropertyMetadata(typeof(SpinnerControl)) + ); + } + // +} diff --git a/dotnet-desktop-guide/framework/wpf/advanced/snippets/dependency-property-value-precedence/xaml/Properties/Resources.Designer.cs b/dotnet-desktop-guide/framework/wpf/advanced/snippets/dependency-property-value-precedence/xaml/Properties/Resources.Designer.cs new file mode 100644 index 0000000..64552f9 --- /dev/null +++ b/dotnet-desktop-guide/framework/wpf/advanced/snippets/dependency-property-value-precedence/xaml/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/framework/wpf/advanced/snippets/dependency-property-value-precedence/xaml/Properties/Resources.resx b/dotnet-desktop-guide/framework/wpf/advanced/snippets/dependency-property-value-precedence/xaml/Properties/Resources.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/dotnet-desktop-guide/framework/wpf/advanced/snippets/dependency-property-value-precedence/xaml/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/samples/snippets/csharp/VS_Snippets_Wpf/PropertiesOvwSupport/CSharp/page4.xaml b/dotnet-desktop-guide/samples/snippets/csharp/VS_Snippets_Wpf/PropertiesOvwSupport/CSharp/page4.xaml index 8e3dc2e..75e7eee 100644 --- a/dotnet-desktop-guide/samples/snippets/csharp/VS_Snippets_Wpf/PropertiesOvwSupport/CSharp/page4.xaml +++ b/dotnet-desktop-guide/samples/snippets/csharp/VS_Snippets_Wpf/PropertiesOvwSupport/CSharp/page4.xaml @@ -4,27 +4,30 @@ x:Class="MyNamespace.MyCode" Loaded="BAQ" > - - - - Hello - - - - + + + + + + + + + + + - From 090e480dcf81f8cf99be833e83cca9be95da9dcd Mon Sep 17 00:00:00 2001 From: Tris Shores <86677757+v-trisshores@users.noreply.github.com> Date: Thu, 21 Oct 2021 14:55:42 -0500 Subject: [PATCH 4/9] Modify redirects generator to update a specified _.openpublishing.redirection_ file (#1181) --- redirects_generator/readme.md | 4 +++- redirects_generator/redirects.cs | 33 ++++++++++++++++++++++++++++++-- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/redirects_generator/readme.md b/redirects_generator/readme.md index babe9ac..40f3ebe 100644 --- a/redirects_generator/readme.md +++ b/redirects_generator/readme.md @@ -1,4 +1,6 @@ -This tool uses the _definitions.json_ file to generate a _.openpublishing.redirection_ file. If a _.openpublishing.redirection_ file exists in the folder, it's updated and appended to. +This tool uses the _definitions.json_ file to generate a _.openpublishing.redirection_ file. If a _.openpublishing.redirection_ file exists in the folder, it's copied to the output folder and updated and appended to there. + +Pass in the file path of a _.openpublishing.redirection_ file, and it'll be updated in-place. e.g. redirs.exe "c:\repos\dotnet\docs-desktop\.openpublishing.redirection.json" The definitions generate two-way redirects between versioned content. The definition file is a json file that has some config at the start: diff --git a/redirects_generator/redirects.cs b/redirects_generator/redirects.cs index 962541c..b693037 100644 --- a/redirects_generator/redirects.cs +++ b/redirects_generator/redirects.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.IO; using System.Text.Json; using System.Text.Json.Serialization; @@ -7,10 +8,22 @@ const string OutputFile = ".openpublishing.redirection.json"; JsonSerializerOptions options = new JsonSerializerOptions { - Converters = { new System.Text.Json.Serialization.JsonStringEnumConverter() }, - ReadCommentHandling = JsonCommentHandling.Skip + Converters = { new JsonStringEnumConverter() }, + ReadCommentHandling = JsonCommentHandling.Skip, + WriteIndented = true }; +// If a .openpublishing.redirection.json path is provided, +// then copy that file to the output folder. +if (args.Length == 1 && File.Exists(args[0])) +{ + // Get passed in .openpublishing.redirection.json path. + string srcRedirectFilePath = args[0]; + + // Copy .openpublishing.redirection.json to output folder. + File.Copy(srcRedirectFilePath, OutputFile, overwrite: true); +} + // Load the definitions Console.WriteLine("Loading 'definitions.json'"); Document document = JsonSerializer.Deserialize(System.IO.File.ReadAllText("definitions.json"), options); @@ -63,6 +76,22 @@ if (System.IO.File.Exists(OutputFile)) Console.WriteLine($"Writing '{OutputFile}'"); System.IO.File.WriteAllText(OutputFile, JsonSerializer.Serialize(redirects)); +// If a .openpublishing.redirection.json path is provided, +// then overwrite it with the formatted new content. +if (args.Length == 1 && File.Exists(args[0])) +{ + // Get passed in .openpublishing.redirection.json path. + string srcRedirectFilePath = args[0]; + + // Format new json content. + string formattedJson = JsonSerializer.Serialize(redirects, options); + formattedJson = formattedJson.Replace(" ", " "); // match existing indent. + formattedJson += "\r\n"; // add newline at end. + + // Save new content to source path. + File.WriteAllText(srcRedirectFilePath, formattedJson); +} + void CreateEntry(string sourceMoniker, string sourceUrl, string targetUrl) { // Opposite repo paths are used here according to moniker From cf712b82b0eb9b586f79dc76ea81a755bd31296d Mon Sep 17 00:00:00 2001 From: Tris Shores <86677757+v-trisshores@users.noreply.github.com> Date: Fri, 22 Oct 2021 11:55:35 -0500 Subject: [PATCH 5/9] Content update - Dependency properties collection (user story 1878471) (#1173) * Add code snippets * Add article and updated code snippets * Resolve conflicts * Make reviewer requested changes * Name class parameters and show how to pass in default value in metedata * Add example for creating a FreezableCollection type dependency property * Add newline * Further edits --- .openpublishing.redirection.json | 8 + .../collection-type-dependency-properties.md | 65 +++++++ .../csharp/App.xaml.cs | 17 ++ .../csharp/AssemblyInfo.cs | 10 ++ .../csharp/CodeSampleCsharp.csproj | 24 +++ .../csharp/MainWindow.xaml | 11 ++ .../csharp/MainWindow.xaml.cs | 141 +++++++++++++++ .../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 | 11 ++ .../vb/MainWindow.xaml.vb | 161 ++++++++++++++++++ dotnet-desktop-guide/net/wpf/toc.yml | 2 + redirects_generator/definitions.json | 5 + 18 files changed, 695 insertions(+) create mode 100644 dotnet-desktop-guide/net/wpf/properties/collection-type-dependency-properties.md create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/collection-type-dependency-properties/csharp/App.xaml.cs create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/collection-type-dependency-properties/csharp/AssemblyInfo.cs create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/collection-type-dependency-properties/csharp/CodeSampleCsharp.csproj create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/collection-type-dependency-properties/csharp/MainWindow.xaml create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/collection-type-dependency-properties/csharp/MainWindow.xaml.cs create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/collection-type-dependency-properties/csharp/Properties/Resources.Designer.cs create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/collection-type-dependency-properties/csharp/Properties/Resources.resx create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/collection-type-dependency-properties/csharp/app.xaml create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/collection-type-dependency-properties/vb/Application.xaml create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/collection-type-dependency-properties/vb/Application.xaml.vb create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/collection-type-dependency-properties/vb/AssemblyInfo.vb create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/collection-type-dependency-properties/vb/CodeSampleVb.vbproj create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/collection-type-dependency-properties/vb/MainWindow.xaml create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/collection-type-dependency-properties/vb/MainWindow.xaml.vb diff --git a/.openpublishing.redirection.json b/.openpublishing.redirection.json index f71b9a8..6343093 100644 --- a/.openpublishing.redirection.json +++ b/.openpublishing.redirection.json @@ -496,6 +496,14 @@ { "source_path": "dotnet-desktop-guide/framework/wpf/properties/how-to-register-an-attached-property.md", "redirect_url": "/dotnet/desktop/wpf/advanced/how-to-register-an-attached-property?view=netframeworkdesktop-4.8" + }, + { + "source_path": "dotnet-desktop-guide/net/wpf/advanced/collection-type-dependency-properties.md", + "redirect_url": "/dotnet/desktop/wpf/properties/collection-type-dependency-properties?view=netdesktop-5.0" + }, + { + "source_path": "dotnet-desktop-guide/framework/wpf/properties/collection-type-dependency-properties.md", + "redirect_url": "/dotnet/desktop/wpf/advanced/collection-type-dependency-properties?view=netframeworkdesktop-4.8" } ] } diff --git a/dotnet-desktop-guide/net/wpf/properties/collection-type-dependency-properties.md b/dotnet-desktop-guide/net/wpf/properties/collection-type-dependency-properties.md new file mode 100644 index 0000000..2a0e88f --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/collection-type-dependency-properties.md @@ -0,0 +1,65 @@ +--- +title: "Collection-type dependency properties" +description: "Learn how to implement a dependency property that's a collection type and how to assign a default collection value." +ms.date: "10/06/2021" +dev_langs: + - "csharp" + - "vb" +helpviewer_keywords: + - "properties [WPF], dependency" + - "properties [WPF], collection-type" + - "dependency properties [WPF]" + - "collection-type properties [WPF]" +--- + + +# Collection-type dependency properties (WPF .NET) + +This article provides guidance and suggested patterns for implementing a dependency property that's a collection type. + +## Implement a collection-type dependency property + +In general, the implementation pattern for a dependency property is a CLR property wrapper backed by a identifier instead of a field or other construct. You can follow the same pattern when you implement a collection-type dependency property. The pattern is more complex if the collection element type is a or a derived class. + +## Initialize the collection + +When you create a dependency property, you typically specify the default value through dependency property metadata instead of specifying an initial property value. However, if your property value is a reference type, the default value should be set in the constructor of the class that registers the dependency property. The dependency property metadata shouldn't include a default reference-type value because that value will be assigned to all instances of the class, creating a singleton class. + +The following example declares an `Aquarium` class that contains a collection of elements in a generic . A default collection value isn't included in the passed to the method, and instead the class constructor is used to set the default collection value to a new generic `List`. + +:::code language="csharp" source="./snippets/collection-type-dependency-properties/csharp/MainWindow.xaml.cs" id="SetCollectionDefaultValueInConstructor"::: +:::code language="vb" source="./snippets/collection-type-dependency-properties/vb/MainWindow.xaml.vb" id="SetCollectionDefaultValueInConstructor"::: + +The following test code instantiates two separate `Aquarium` instances and adds a different `Fish` item to each collection. If you run the code, you'll see that each `Aquarium` instance has a single collection item, as expected. + +:::code language="csharp" source="./snippets/collection-type-dependency-properties/csharp/MainWindow.xaml.cs" id="InitializeAquariums"::: +:::code language="vb" source="./snippets/collection-type-dependency-properties/vb/MainWindow.xaml.vb" id="InitializeAquariums"::: + +But, if you comment out the class constructor and pass the default collection value as to the method, you'll see that each `Aquarium` instance gets two collection items! This is because both `Fish` instances are added to the same list, which is shared by all instances of the Aquarium class. So, when the intent is for each object instance to have its own list, the default value should be set in the class constructor. + +### Initialize a read-write collection + +The following example declares a read-write collection-type dependency property in the `Aquarium` class, using the non-key signature methods and . + +:::code language="csharp" source="./snippets/collection-type-dependency-properties/csharp/MainWindow.xaml.cs" id="ReadWriteDependencyProperty"::: +:::code language="vb" source="./snippets/collection-type-dependency-properties/vb/MainWindow.xaml.vb" id="ReadWriteDependencyProperty"::: + +## FreezableCollection dependency properties + +A collection-type dependency property doesn't automatically report changes in its subproperties. As a result, if you're binding to a collection, the binding might not report changes, invalidating some data binding scenarios. But, if you use for the dependency property type, changes to the properties of collection elements are properly reported and binding works as expected. + +To enable subproperty binding in a collection of dependency objects, use the collection type `FreezableCollection`, with a type constraint of any derived class. + +The following example declares an `Aquarium` class that contains a `FreezableCollection` with a type constraint of . A default collection value isn't included in the passed to the method, and instead the class constructor is used to set the default collection value to a new `FreezableCollection`. + +:::code language="csharp" source="./snippets/collection-type-dependency-properties/csharp/MainWindow.xaml.cs" id="FreezableCollectionAquarium"::: +:::code language="vb" source="./snippets/collection-type-dependency-properties/vb/MainWindow.xaml.vb" id="FreezableCollectionAquarium"::: + +## See also + +- +- [XAML and Custom Classes for WPF](/dotnet/desktop/wpf/advanced/xaml-and-custom-classes-for-wpf?view=netframeworkdesktop-4.8&preserve-view=true) +- [Data Binding Overview](/dotnet/desktop/wpf/data/) +- [Dependency Properties Overview](dependency-properties-overview.md) +- [Custom Dependency Properties](/dotnet/desktop/wpf/advanced/custom-dependency-properties?view=netframeworkdesktop-4.8&preserve-view=true) +- [Dependency Property Metadata](/dotnet/desktop/wpf/advanced/dependency-property-metadata?view=netframeworkdesktop-4.8&preserve-view=true) diff --git a/dotnet-desktop-guide/net/wpf/properties/snippets/collection-type-dependency-properties/csharp/App.xaml.cs b/dotnet-desktop-guide/net/wpf/properties/snippets/collection-type-dependency-properties/csharp/App.xaml.cs new file mode 100644 index 0000000..3128552 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/collection-type-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/collection-type-dependency-properties/csharp/AssemblyInfo.cs b/dotnet-desktop-guide/net/wpf/properties/snippets/collection-type-dependency-properties/csharp/AssemblyInfo.cs new file mode 100644 index 0000000..8b5504e --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/collection-type-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/collection-type-dependency-properties/csharp/CodeSampleCsharp.csproj b/dotnet-desktop-guide/net/wpf/properties/snippets/collection-type-dependency-properties/csharp/CodeSampleCsharp.csproj new file mode 100644 index 0000000..8824b2f --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/collection-type-dependency-properties/csharp/CodeSampleCsharp.csproj @@ -0,0 +1,24 @@ + + + + WinExe + net5.0-windows + true + + + + + True + True + Resources.resx + + + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + diff --git a/dotnet-desktop-guide/net/wpf/properties/snippets/collection-type-dependency-properties/csharp/MainWindow.xaml b/dotnet-desktop-guide/net/wpf/properties/snippets/collection-type-dependency-properties/csharp/MainWindow.xaml new file mode 100644 index 0000000..e3a44de --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/collection-type-dependency-properties/csharp/MainWindow.xaml @@ -0,0 +1,11 @@ + + + + + + + + diff --git a/dotnet-desktop-guide/net/wpf/properties/snippets/collection-type-dependency-properties/csharp/MainWindow.xaml.cs b/dotnet-desktop-guide/net/wpf/properties/snippets/collection-type-dependency-properties/csharp/MainWindow.xaml.cs new file mode 100644 index 0000000..4e9c314 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/collection-type-dependency-properties/csharp/MainWindow.xaml.cs @@ -0,0 +1,141 @@ +using System.Collections.Generic; +using System.Windows; + +namespace CodeSampleCsharp +{ + /// + /// Interaction logic for MainWindow.xaml. + /// + public partial class MainWindow : Window + { + // + private void InitializeAquariums(object sender, RoutedEventArgs e) + { + Aquarium aquarium1 = new(); + Aquarium aquarium2 = new(); + aquarium1.AquariumContents.Add(new Fish()); + aquarium2.AquariumContents.Add(new Fish()); + MessageBox.Show( + $"Aquarium1 contains {aquarium1.AquariumContents.Count} fish\r\n" + + $"Aquarium2 contains {aquarium2.AquariumContents.Count} fish"); + } + // + } + + // + public class Aquarium : DependencyObject + { + // Register a dependency property with the specified property name, + // property type, owner type, and property metadata. + private static readonly DependencyPropertyKey s_aquariumContentsPropertyKey = + DependencyProperty.RegisterReadOnly( + name: "AquariumContents", + propertyType: typeof(List), + ownerType: typeof(Aquarium), + typeMetadata: new FrameworkPropertyMetadata() + //typeMetadata: new FrameworkPropertyMetadata(new List()) + ); + + // Store the dependency property identifier as a static member of the class. + public static readonly DependencyProperty AquariumContentsProperty = + s_aquariumContentsPropertyKey.DependencyProperty; + + // Set the default collection value in a class constructor. + public Aquarium() => SetValue(s_aquariumContentsPropertyKey, new List()); + + // Declare a read-only property. + public List AquariumContents => + (List)GetValue(AquariumContentsProperty); + } + + public class Fish : FrameworkElement { } + // + + public class ReadWriteAquariumContents + { + private static void InitializeAquariums() + { + Aquarium aquarium1 = new(); + Aquarium aquarium2 = new(); + aquarium1.AquariumContents.Add(new Fish()); + aquarium2.AquariumContents.Add(new Fish()); + aquarium2.AquariumContents = new List(); + MessageBox.Show( + $"Aquarium1 contains {aquarium1.AquariumContents.Count} fish\r\n" + + $"Aquarium2 contains {aquarium2.AquariumContents.Count} fish"); + } + + // + public class Aquarium : DependencyObject + { + // Register a dependency property with the specified property name, + // property type, and owner type. + private static readonly DependencyProperty s_aquariumContentsProperty = + DependencyProperty.Register( + name: "AquariumContents", + propertyType: typeof(List), + ownerType: typeof(Aquarium) + ); + + // Store the dependency property identifier as a static member of the class. + public static readonly DependencyProperty AquariumContentsProperty = + s_aquariumContentsProperty; + + // Set the default collection value in a class constructor. + public Aquarium() => SetValue(s_aquariumContentsProperty, new List()); + + // Declare a read-write property. + public List AquariumContents + { + get => (List)GetValue(AquariumContentsProperty); + set => SetValue(AquariumContentsProperty, value); + } + } + // + + public class Fish : FrameworkElement { } + } + + public class FreezableCollectionAquarium + { + public static void InitializeAquariums() + { + Aquarium aquarium1 = new(); + Aquarium aquarium2 = new(); + aquarium1.AquariumContents.Add(new Fish()); + aquarium2.AquariumContents.Add(new Fish()); + MessageBox.Show( + $"Aquarium1 contains {aquarium1.AquariumContents.Count} fish\r\n" + + $"Aquarium2 contains {aquarium2.AquariumContents.Count} fish"); + } + + // + public class Aquarium : DependencyObject + { + // Register a dependency property with the specified property name, + // property type, and owner type. + private static readonly DependencyPropertyKey s_aquariumContentsPropertyKey = + DependencyProperty.RegisterReadOnly( + name: "AquariumContents", + propertyType: typeof(FreezableCollection), + ownerType: typeof(Aquarium), + typeMetadata: new FrameworkPropertyMetadata() + ); + + // Store the dependency property identifier as a static member of the class. + public static readonly DependencyProperty AquariumContentsProperty = + s_aquariumContentsPropertyKey.DependencyProperty; + + // Set the default collection value in a class constructor. + public Aquarium() => SetValue(s_aquariumContentsPropertyKey, new FreezableCollection()); + + // Declare a read-only property. + public FreezableCollection AquariumContents => + (FreezableCollection)GetValue(AquariumContentsProperty); + } + + // + + public class Fish : FrameworkElement { } + } +} diff --git a/dotnet-desktop-guide/net/wpf/properties/snippets/collection-type-dependency-properties/csharp/Properties/Resources.Designer.cs b/dotnet-desktop-guide/net/wpf/properties/snippets/collection-type-dependency-properties/csharp/Properties/Resources.Designer.cs new file mode 100644 index 0000000..64552f9 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/collection-type-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/collection-type-dependency-properties/csharp/Properties/Resources.resx b/dotnet-desktop-guide/net/wpf/properties/snippets/collection-type-dependency-properties/csharp/Properties/Resources.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/collection-type-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/collection-type-dependency-properties/csharp/app.xaml b/dotnet-desktop-guide/net/wpf/properties/snippets/collection-type-dependency-properties/csharp/app.xaml new file mode 100644 index 0000000..867d2f0 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/collection-type-dependency-properties/csharp/app.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/dotnet-desktop-guide/net/wpf/properties/snippets/collection-type-dependency-properties/vb/Application.xaml b/dotnet-desktop-guide/net/wpf/properties/snippets/collection-type-dependency-properties/vb/Application.xaml new file mode 100644 index 0000000..f225972 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/collection-type-dependency-properties/vb/Application.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/dotnet-desktop-guide/net/wpf/properties/snippets/collection-type-dependency-properties/vb/Application.xaml.vb b/dotnet-desktop-guide/net/wpf/properties/snippets/collection-type-dependency-properties/vb/Application.xaml.vb new file mode 100644 index 0000000..084cbe9 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/collection-type-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/collection-type-dependency-properties/vb/AssemblyInfo.vb b/dotnet-desktop-guide/net/wpf/properties/snippets/collection-type-dependency-properties/vb/AssemblyInfo.vb new file mode 100644 index 0000000..025ee72 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/collection-type-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/collection-type-dependency-properties/vb/CodeSampleVb.vbproj b/dotnet-desktop-guide/net/wpf/properties/snippets/collection-type-dependency-properties/vb/CodeSampleVb.vbproj new file mode 100644 index 0000000..c7ae1cc --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/collection-type-dependency-properties/vb/CodeSampleVb.vbproj @@ -0,0 +1,22 @@ + + + + WinExe + net5.0-windows + CodeSampleVb + true + + + + + + + + + + + + + + + diff --git a/dotnet-desktop-guide/net/wpf/properties/snippets/collection-type-dependency-properties/vb/MainWindow.xaml b/dotnet-desktop-guide/net/wpf/properties/snippets/collection-type-dependency-properties/vb/MainWindow.xaml new file mode 100644 index 0000000..2080a2f --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/collection-type-dependency-properties/vb/MainWindow.xaml @@ -0,0 +1,11 @@ + + + + + + + + diff --git a/dotnet-desktop-guide/net/wpf/properties/snippets/collection-type-dependency-properties/vb/MainWindow.xaml.vb b/dotnet-desktop-guide/net/wpf/properties/snippets/collection-type-dependency-properties/vb/MainWindow.xaml.vb new file mode 100644 index 0000000..e031016 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/collection-type-dependency-properties/vb/MainWindow.xaml.vb @@ -0,0 +1,161 @@ +Namespace CodeSampleVb + + ' + ' Interaction logic for MainWindow.xaml. + ' + Partial Public Class MainWindow + Inherits Window + + Public Sub New() + InitializeComponent() + End Sub + + ' + Private Sub InitializeAquariums(sender As Object, e As RoutedEventArgs) + Dim aquarium1 As New Aquarium() + Dim aquarium2 As New Aquarium() + aquarium1.AquariumContents.Add(New Fish()) + aquarium2.AquariumContents.Add(New Fish()) + MessageBox.Show($"Aquarium1 contains {aquarium1.AquariumContents.Count} fish{Environment.NewLine}" + + $"Aquarium2 contains {aquarium2.AquariumContents.Count} fish") + End Sub + ' + + End Class + + ' + Public Class Aquarium + Inherits DependencyObject + + ' Register a dependency property with the specified property name, + ' property type, owner type, and property metadata. + Private Shared ReadOnly s_aquariumContentsPropertyKey As DependencyPropertyKey = + DependencyProperty.RegisterReadOnly( + name:="AquariumContents", + propertyType:=GetType(List(Of FrameworkElement)), + ownerType:=GetType(Aquarium), + typeMetadata:=New FrameworkPropertyMetadata()) + 'typeMetadata:=New FrameworkPropertyMetadata(New List(Of FrameworkElement))) + + ' Store the dependency property identifier as a static member of the class. + Public Shared ReadOnly AquariumContentsProperty As DependencyProperty = + s_aquariumContentsPropertyKey.DependencyProperty + + ' Set the default collection value in a class constructor. + Public Sub New() + SetValue(s_aquariumContentsPropertyKey, New List(Of FrameworkElement)()) + End Sub + + ' Declare a read-only property. + Public ReadOnly Property AquariumContents As List(Of FrameworkElement) + Get + Return CType(GetValue(AquariumContentsProperty), List(Of FrameworkElement)) + End Get + End Property + End Class + + Public Class Fish + Inherits FrameworkElement + End Class + ' + + Public Class ReadWriteAquariumContents + + Public Shared Sub InitializeAquariums() + Dim aquarium1 As New Aquarium() + Dim aquarium2 As New Aquarium() + aquarium1.AquariumContents.Add(New Fish()) + aquarium2.AquariumContents.Add(New Fish()) + aquarium2.AquariumContents = New List(Of FrameworkElement)() + MessageBox.Show($"Aquarium1 contains {aquarium1.AquariumContents.Count} fish{Environment.NewLine}" + + $"Aquarium2 contains {aquarium2.AquariumContents.Count} fish") + End Sub + + ' + Public Class Aquarium + Inherits DependencyObject + + ' Register a dependency property with the specified property name, + ' property type, and owner type. + Private Shared ReadOnly s_aquariumContentsProperty As DependencyProperty = + DependencyProperty.Register( + name:="AquariumContents", + propertyType:=GetType(List(Of FrameworkElement)), + ownerType:=GetType(Aquarium)) + + ' Store the dependency property identifier as a static member of the class. + Public Shared ReadOnly AquariumContentsProperty As DependencyProperty = + s_aquariumContentsProperty + + ' Set the default collection value in a class constructor. + Public Sub New() + SetValue(s_aquariumContentsProperty, New List(Of FrameworkElement)()) + End Sub + + ' Declare a read-write property. + Public Property AquariumContents As List(Of FrameworkElement) + Get + Return CType(GetValue(AquariumContentsProperty), List(Of FrameworkElement)) + End Get + Set + SetValue(AquariumContentsProperty, Value) + End Set + End Property + End Class + ' + + Public Class Fish + Inherits FrameworkElement + End Class + + End Class + + Public Class FreezableCollectionAquarium + + Public Shared Sub InitializeAquariums() + Dim aquarium1 As New Aquarium() + Dim aquarium2 As New Aquarium() + aquarium1.AquariumContents.Add(New Fish()) + aquarium2.AquariumContents.Add(New Fish()) + MessageBox.Show($"Aquarium1 contains {aquarium1.AquariumContents.Count} fish{Environment.NewLine}" + + $"Aquarium2 contains {aquarium2.AquariumContents.Count} fish") + End Sub + + ' + Public Class Aquarium + Inherits DependencyObject + + ' Register a dependency property with the specified property name, + ' property type, and owner type. + Private Shared ReadOnly s_aquariumContentsPropertyKey As DependencyPropertyKey = + DependencyProperty.RegisterReadOnly( + name:="AquariumContents", + propertyType:=GetType(FreezableCollection(Of FrameworkElement)), + ownerType:=GetType(Aquarium), + typeMetadata:=New FrameworkPropertyMetadata()) + + ' Store the dependency property identifier as a static member of the class. + Public Shared ReadOnly AquariumContentsProperty As DependencyProperty = + s_aquariumContentsPropertyKey.DependencyProperty + + ' Set the default collection value in a class constructor. + Public Sub New() + SetValue(s_aquariumContentsPropertyKey, New FreezableCollection(Of FrameworkElement)()) + End Sub + + ' Declare a read-only property. + Public ReadOnly Property AquariumContents As FreezableCollection(Of FrameworkElement) + Get + Return CType(GetValue(AquariumContentsProperty), FreezableCollection(Of FrameworkElement)) + End Get + End Property + End Class + ' + + Public Class Fish + Inherits FrameworkElement + End Class + + End Class + +End Namespace diff --git a/dotnet-desktop-guide/net/wpf/toc.yml b/dotnet-desktop-guide/net/wpf/toc.yml index 86cf216..cc3d519 100644 --- a/dotnet-desktop-guide/net/wpf/toc.yml +++ b/dotnet-desktop-guide/net/wpf/toc.yml @@ -86,6 +86,8 @@ items: href: properties/dependency-property-value-precedence.md - name: Register an attached property href: properties/how-to-register-an-attached-property.md + - name: Collection-type dependency properties + href: properties/collection-type-dependency-properties.md - name: Resources items: - name: Overview diff --git a/redirects_generator/definitions.json b/redirects_generator/definitions.json index 083db02..3ff61d6 100644 --- a/redirects_generator/definitions.json +++ b/redirects_generator/definitions.json @@ -334,6 +334,11 @@ "SourceUrl": "/dotnet/desktop/wpf/advanced/how-to-register-an-attached-property?view=netframeworkdesktop-4.8", "TargetUrl": "/dotnet/desktop/wpf/properties/how-to-register-an-attached-property?view=netdesktop-5.0" }, + { + "Redirect": "TwoWay", + "SourceUrl": "/dotnet/desktop/wpf/advanced/collection-type-dependency-properties?view=netframeworkdesktop-4.8", + "TargetUrl": "/dotnet/desktop/wpf/properties/collection-type-dependency-properties?view=netdesktop-5.0" + }, // Systems - XAML { From 4f0101b05cd2ea16812e4845258f3e5cd01d423c Mon Sep 17 00:00:00 2001 From: Tris Shores <86677757+v-trisshores@users.noreply.github.com> Date: Fri, 22 Oct 2021 12:23:20 -0500 Subject: [PATCH 6/9] Add article, code projects, toc, and redirects (#1178) Co-authored-by: Andy (Steve) De George <67293991+adegeo@users.noreply.github.com> --- .openpublishing.redirection.json | 8 ++ .../attached-properties-overview.md | 134 ++++++++++++++++++ .../csharp/App.xaml.cs | 11 ++ .../csharp/AssemblyInfo.cs | 10 ++ .../csharp/CodeSampleCsharp.csproj | 24 ++++ .../csharp/MainWindow.xaml | 15 ++ .../csharp/MainWindow.xaml.cs | 57 ++++++++ .../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 | 15 ++ .../vb/MainWindow.xaml.vb | 55 +++++++ dotnet-desktop-guide/net/wpf/toc.yml | 4 + redirects_generator/definitions.json | 9 +- 18 files changed, 580 insertions(+), 2 deletions(-) create mode 100644 dotnet-desktop-guide/net/wpf/properties/attached-properties-overview.md create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/attached-properties-overview/csharp/App.xaml.cs create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/attached-properties-overview/csharp/AssemblyInfo.cs create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/attached-properties-overview/csharp/CodeSampleCsharp.csproj create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/attached-properties-overview/csharp/MainWindow.xaml create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/attached-properties-overview/csharp/MainWindow.xaml.cs create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/attached-properties-overview/csharp/Properties/Resources.Designer.cs create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/attached-properties-overview/csharp/Properties/Resources.resx create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/attached-properties-overview/csharp/app.xaml create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/attached-properties-overview/vb/Application.xaml create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/attached-properties-overview/vb/Application.xaml.vb create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/attached-properties-overview/vb/AssemblyInfo.vb create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/attached-properties-overview/vb/CodeSampleVb.vbproj create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/attached-properties-overview/vb/MainWindow.xaml create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/attached-properties-overview/vb/MainWindow.xaml.vb diff --git a/.openpublishing.redirection.json b/.openpublishing.redirection.json index 6343093..8c307c9 100644 --- a/.openpublishing.redirection.json +++ b/.openpublishing.redirection.json @@ -489,6 +489,14 @@ "source_path": "dotnet-desktop-guide/framework/wpf/properties/dependency-property-value-precedence.md", "redirect_url": "/dotnet/desktop/wpf/advanced/dependency-property-value-precedence?view=netframeworkdesktop-4.8" }, + { + "source_path": "dotnet-desktop-guide/net/wpf/advanced/attached-properties-overview.md", + "redirect_url": "/dotnet/desktop/wpf/properties/attached-properties-overview?view=netdesktop-5.0" + }, + { + "source_path": "dotnet-desktop-guide/framework/wpf/properties/attached-properties-overview.md", + "redirect_url": "/dotnet/desktop/wpf/advanced/attached-properties-overview?view=netframeworkdesktop-4.8" + }, { "source_path": "dotnet-desktop-guide/net/wpf/advanced/how-to-register-an-attached-property.md", "redirect_url": "/dotnet/desktop/wpf/properties/how-to-register-an-attached-property?view=netdesktop-5.0" diff --git a/dotnet-desktop-guide/net/wpf/properties/attached-properties-overview.md b/dotnet-desktop-guide/net/wpf/properties/attached-properties-overview.md new file mode 100644 index 0000000..b2f2e87 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/attached-properties-overview.md @@ -0,0 +1,134 @@ +--- +title: "Attached properties overview" +description: "Learn about the WPF property system and the capabilities of an attached property, which are global properties settable on any object." +ms.date: "10/14/2021" +ms.topic: overview +dev_langs: + - "csharp" + - "vb" +helpviewer_keywords: + - "attached properties [WPF Designer]" +--- + + +# Attached properties overview (WPF .NET) + +An attached property is a Extensible Application Markup Language (XAML) concept. Attached properties enable extra property/value pairs to be set on any XAML element, even though the element doesn't define those extra properties in its object model. The extra properties are globally accessible. Attached properties are typically defined as a specialized form of dependency property that doesn't have a conventional property wrapper. + +## 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 XAML and know how to write Windows Presentation Foundation (WPF) applications. + +## Why use attached properties + +An attached property lets a child element specify a unique value for a property that's defined in a parent element. A common scenario is a child element specifying how it should be rendered in the UI by its parent element. For example, is an attached property because it's set on child elements of a , not the `DockPanel` itself. The `DockPanel` class defines a static field, named , and then provides and methods as public accessors for the attached property. + +## Attached properties in XAML + +In XAML, you set attached properties by using the syntax `.`, where the attached property provider is the class that defines the attached property. The following example shows how a child element of can set the property value. + +:::code language="xaml" source="./snippets/attached-properties-overview/csharp/MainWindow.xaml" id="SetAttachedPropertyInXaml"::: + +The usage is similar to a static property in that you reference the type that owns and registers the attached property (for example, ), not the instance name. + +When you specify an attached property using a XAML attribute, only the set action is applicable. You can't directly get a property value through XAML, although there are some indirect mechanisms for comparing values, such as [triggers in styles](/dotnet/desktop/wpf/controls/styles-templates-overview#triggers). + +### Attached properties in WPF + +Attached properties are a XAML concept, dependency properties are a WPF concept. In WPF, most UI-related attached properties on WPF types are implemented as dependency properties. WPF attached properties that are implemented as dependency properties support dependency property concepts, such as property metadata including default values from metadata. + +## Attached property usage models + +Although any object can set an attached property value, that doesn't mean setting a value will produce a tangible result or the value will be used by another object. The main purpose of attached properties is to provide a way for objects from a wide variety of class hierarchies and logical relationships to report common information to the type that defines the attached property. Attached property usage typically follows one of these models: + +- The type that defines the attached property is the parent of the elements that set values for the attached property. The parent type iterates its child objects through internal logic that acts on the object tree structure, obtains the values, and acts on those values in some manner. +- The type that defines the attached property is used as the child element for various possible parent elements and content models. +- The type that defines the attached property represents a service. Other types set values for the attached property. Then, when the element that set the property is evaluated in the context of the service, the attached property values are obtained through internal logic of the service class. + +### An example of a parent-defined attached property + +The typical scenario where WPF defines an attached property is when a parent element supports a child element collection, and the parent element implements a behavior based on data reported by each of its child elements. + + defines the attached property. `DockPanel` has class-level code, specifically and , that's part of its rendering logic. A `DockPanel` instance checks whether any of its immediate child elements have set a value for `DockPanel.Dock`. If so, those values become inputs to the rendering logic applied to each child element. Although it's theoretically possible for attached properties to influence elements beyond the immediate parent, the defined behavior for a nested `DockPanel` instance is to only interact with its immediate child element collection. So, if you set `DockPanel.Dock` on an element that has no `DockPanel` parent, no error or exception will be raised and you would have created a global property value that won't be consumed by any `DockPanel`. + +## Attached properties in code + +Attached properties in WPF don't have the typical CLR `get` and `set` wrapper methods because the properties might be set from outside of the CLR namespace. To permit a XAML processor to set those values when parsing XAML, the class that defines the attached property must implement dedicated accessor methods in the form of `Get` and `Set`. + +You can also use the dedicated accessor methods to get and set an attached property in code, as shown in the following example. In the example, `myTextBox` is an instance of the class. + +:::code language="csharp" source="./snippets/attached-properties-overview/csharp/MainWindow.xaml.cs" id="SetAttachedPropertyInCode"::: +:::code language="vb" source="./snippets/attached-properties-overview/vb/MainWindow.xaml.vb" id="SetAttachedPropertyInCode"::: + +If you don't add `myTextBox` as a child element of `myDockPanel`, calling `SetDock` won't raise an exception or have any effect. Only a value set on a child element of a `DockPanel` can affect rendering, and the rendering will be the same whether you set the value before or after adding the child element to the `DockPanel`. + +From a code perspective, an attached property is like a backing field that has method accessors instead of property accessors, and can be set on any object without first needing to be defined on those objects. + +## Attached property metadata + +Metadata for an attached property is generally no different than for a dependency property. When registering an attached property, use to specify characteristics of the property, such as whether the property affects rendering or measurement. When you specify a default value by overriding attached property metadata, that value becomes the default for the implicit attached property on instances of the overriding class. If an attached property value isn't otherwise set, the default value is reported when the property is queried by using the `Get` accessor with an instance of the class where you specified the metadata. + +To enable property value inheritance on a property, use attached properties instead of non-attached dependency properties. For more information, see [Property value inheritance](/dotnet/desktop/wpf/advanced/property-value-inheritance?view=netframeworkdesktop-4.8&preserve-view=true). + +## Custom attached properties + +### When to create an attached property + +Creating an attached property is useful when: + +- You need a property setting mechanism available to classes other than the defining class. A common scenario is for UI layout, for instance , , and are all examples of existing layout properties. In the layout scenario, child elements of a layout-controlling element are able to express layout requirements to their layout parent and to set a value for an attached property defined by the parent. + +- One of your classes represents a service, and you want other classes to integrate the service more transparently. +- You want Visual Studio WPF Designer support, such as the ability to edit a property through the **Properties** window. For more information, see [Control authoring overview](/dotnet/desktop/wpf/controls/control-authoring-overview?view=netframeworkdesktop-4.8&preserve-view=true). +- You want to use property value inheritance. + +### How to create an attached property + +If your class defines an attached property solely for use by other types, then your class doesn't need to derive from . Otherwise, follow the WPF model of having an attached property also be a dependency property, by deriving your class from `DependencyObject`. + +Define your attached property as a dependency in the defining class by declaring a `public static readonly` field of type . Then, assign the return value of the method to the field, which is also known as the *dependency property identifier*. Follow the WPF property naming convention that distinguishes fields from the properties that they represent, by naming the identifier field `Property`. Also, provide static `Get` and `Set` accessor methods, which lets the property system access your attached property. + +The following example shows how to register a dependency property using the method, and how to define the accessor methods. In the example, the name of the attached property is `HasFish`, so the identifier field is named `HasFishProperty`, and the accessor methods are named `GetHasFish` and `SetHasFish`. + +:::code language="csharp" source="./snippets/attached-properties-overview/csharp/MainWindow.xaml.cs" id="RegisterAttachedProperty"::: +:::code language="vb" source="./snippets/attached-properties-overview/vb/MainWindow.xaml.vb" id="RegisterAttachedProperty"::: + +#### The Get accessor + +The `get` accessor method signature is `public static object Get(object target)`, where: + +- `target` is the object from which the attached property is read. The `target` type can be more specific than `object`. For example, the accessor method types the `target` as because the attached property is intended to be set on `UIElement` instances. +- The return type can be more specific than `object`. For example, the method types the returned value as because the return value should be a `Dock` enumeration. + +> [!NOTE] +> The `get` accessor for an attached property is required for data binding support in design tools, such as Visual Studio or Blend for Visual Studio. + +#### The Set accessor + +The `set` accessor method signature is `public static void Set(object target, object value)`, where: + +- `target` is the object on which the attached property is written. The `target` type can be more specific than `object`. For example, the method types the `target` as because the attached property is intended to be set on instances. +- The `value` type can be more specific than `object`. For example, the method requires a value. The XAML loader needs to be able to generate the `value` type from the markup string that represents the attached property value. So, there must be type conversion, value serializer, or markup extension support for the type you use. + +### Attached property attributes + +WPF defines several .NET attributes that provide information about attached properties to reflection processes and also to consumers of reflection and property information, such as designers. Designers use WPF defined .NET attributes to limit the properties shown in the properties window, to avoid overwhelming users with a global list of all attached properties. You might consider applying these attributes to your own custom attached properties. The purpose and syntax of .NET attributes is described in these reference pages: + +- +- +- +- + +## Learn more + +- For more information about creating an attached property, see [Register an attached property](/dotnet/desktop/wpf/advanced/how-to-register-an-attached-property?view=netframeworkdesktop-4.8&preserve-view=true). +- For more advanced usage scenarios for dependency properties and attached properties, see [Custom dependency properties](/dotnet/desktop/wpf/advanced/custom-dependency-properties?view=netframeworkdesktop-4.8&preserve-view=true). +- You can register a property as both an attached property and a dependency property, and include conventional property wrappers. In this way, a property can be set on an element by using property wrappers, and also on any other element by using XAML attached property syntax. For an example, see . + +## See also + +- +- [Dependency properties overview](dependency-properties-overview.md) +- [Custom dependency properties](/dotnet/desktop/wpf/advanced/custom-dependency-properties?view=netframeworkdesktop-4.8&preserve-view=true) +- [XAML in WPF](/dotnet/desktop/wpf/xaml/) +- [How to: Register an attached property](/dotnet/desktop/wpf/advanced/how-to-register-an-attached-property?view=netframeworkdesktop-4.8&preserve-view=true) diff --git a/dotnet-desktop-guide/net/wpf/properties/snippets/attached-properties-overview/csharp/App.xaml.cs b/dotnet-desktop-guide/net/wpf/properties/snippets/attached-properties-overview/csharp/App.xaml.cs new file mode 100644 index 0000000..bdad66d --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/attached-properties-overview/csharp/App.xaml.cs @@ -0,0 +1,11 @@ +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/attached-properties-overview/csharp/AssemblyInfo.cs b/dotnet-desktop-guide/net/wpf/properties/snippets/attached-properties-overview/csharp/AssemblyInfo.cs new file mode 100644 index 0000000..8b5504e --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/attached-properties-overview/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/attached-properties-overview/csharp/CodeSampleCsharp.csproj b/dotnet-desktop-guide/net/wpf/properties/snippets/attached-properties-overview/csharp/CodeSampleCsharp.csproj new file mode 100644 index 0000000..8824b2f --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/attached-properties-overview/csharp/CodeSampleCsharp.csproj @@ -0,0 +1,24 @@ + + + + WinExe + net5.0-windows + true + + + + + True + True + Resources.resx + + + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + diff --git a/dotnet-desktop-guide/net/wpf/properties/snippets/attached-properties-overview/csharp/MainWindow.xaml b/dotnet-desktop-guide/net/wpf/properties/snippets/attached-properties-overview/csharp/MainWindow.xaml new file mode 100644 index 0000000..b3f7c28 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/attached-properties-overview/csharp/MainWindow.xaml @@ -0,0 +1,15 @@ + + + + + + + Enter text + + + + + diff --git a/dotnet-desktop-guide/net/wpf/properties/snippets/attached-properties-overview/csharp/MainWindow.xaml.cs b/dotnet-desktop-guide/net/wpf/properties/snippets/attached-properties-overview/csharp/MainWindow.xaml.cs new file mode 100644 index 0000000..58604d2 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/attached-properties-overview/csharp/MainWindow.xaml.cs @@ -0,0 +1,57 @@ +using System.Windows; +using System.Windows.Controls; + +namespace CodeSampleCsharp +{ + /// + /// Interaction logic for MainWindow.xaml. + /// + public partial class MainWindow : Window + { + public MainWindow() + { + InitializeComponent(); + + SetAttachedPropertyInCode(); + } + + public static void SetAttachedPropertyInCode() + { + // + DockPanel myDockPanel = new(); + TextBox myTextBox = new(); + myTextBox.Text = "Enter text"; + + // Add child element to the DockPanel. + myDockPanel.Children.Add(myTextBox); + + // Set the attached property value. + DockPanel.SetDock(myTextBox, Dock.Top); + // + } + } + + // + public class Aquarium : DependencyObject + { + // Register an attached dependency property with the specified + // property name, property type, owner type, and property metadata. + public static readonly DependencyProperty HasFishProperty = + DependencyProperty.RegisterAttached( + "HasFish", + typeof(bool), + typeof(Aquarium), + new FrameworkPropertyMetadata(defaultValue: false, + flags: FrameworkPropertyMetadataOptions.AffectsRender) + ); + + // Declare a get accessor method. + public static bool GetHasFish(UIElement target) => + (bool)target.GetValue(HasFishProperty); + + // Declare a set accessor method. + public static void SetHasFish(UIElement target, bool value) => + target.SetValue(HasFishProperty, value); + } + // +} diff --git a/dotnet-desktop-guide/net/wpf/properties/snippets/attached-properties-overview/csharp/Properties/Resources.Designer.cs b/dotnet-desktop-guide/net/wpf/properties/snippets/attached-properties-overview/csharp/Properties/Resources.Designer.cs new file mode 100644 index 0000000..64552f9 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/attached-properties-overview/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/attached-properties-overview/csharp/Properties/Resources.resx b/dotnet-desktop-guide/net/wpf/properties/snippets/attached-properties-overview/csharp/Properties/Resources.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/attached-properties-overview/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/attached-properties-overview/csharp/app.xaml b/dotnet-desktop-guide/net/wpf/properties/snippets/attached-properties-overview/csharp/app.xaml new file mode 100644 index 0000000..867d2f0 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/attached-properties-overview/csharp/app.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/dotnet-desktop-guide/net/wpf/properties/snippets/attached-properties-overview/vb/Application.xaml b/dotnet-desktop-guide/net/wpf/properties/snippets/attached-properties-overview/vb/Application.xaml new file mode 100644 index 0000000..f225972 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/attached-properties-overview/vb/Application.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/dotnet-desktop-guide/net/wpf/properties/snippets/attached-properties-overview/vb/Application.xaml.vb b/dotnet-desktop-guide/net/wpf/properties/snippets/attached-properties-overview/vb/Application.xaml.vb new file mode 100644 index 0000000..084cbe9 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/attached-properties-overview/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/attached-properties-overview/vb/AssemblyInfo.vb b/dotnet-desktop-guide/net/wpf/properties/snippets/attached-properties-overview/vb/AssemblyInfo.vb new file mode 100644 index 0000000..025ee72 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/attached-properties-overview/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/attached-properties-overview/vb/CodeSampleVb.vbproj b/dotnet-desktop-guide/net/wpf/properties/snippets/attached-properties-overview/vb/CodeSampleVb.vbproj new file mode 100644 index 0000000..c7ae1cc --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/attached-properties-overview/vb/CodeSampleVb.vbproj @@ -0,0 +1,22 @@ + + + + WinExe + net5.0-windows + CodeSampleVb + true + + + + + + + + + + + + + + + diff --git a/dotnet-desktop-guide/net/wpf/properties/snippets/attached-properties-overview/vb/MainWindow.xaml b/dotnet-desktop-guide/net/wpf/properties/snippets/attached-properties-overview/vb/MainWindow.xaml new file mode 100644 index 0000000..06242e3 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/attached-properties-overview/vb/MainWindow.xaml @@ -0,0 +1,15 @@ + + + + + + + Enter text + + + + + diff --git a/dotnet-desktop-guide/net/wpf/properties/snippets/attached-properties-overview/vb/MainWindow.xaml.vb b/dotnet-desktop-guide/net/wpf/properties/snippets/attached-properties-overview/vb/MainWindow.xaml.vb new file mode 100644 index 0000000..6a6c16c --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/attached-properties-overview/vb/MainWindow.xaml.vb @@ -0,0 +1,55 @@ +Namespace CodeSampleVb + + ' + ' Interaction logic for MainWindow.xaml. + ' + Partial Public Class MainWindow + Inherits Window + + Public Sub New() + InitializeComponent() + + SetAttachedPropertyInCode() + End Sub + + Public Shared Sub SetAttachedPropertyInCode() + ' + Dim myDockPanel As DockPanel = New DockPanel() + Dim myTextBox As TextBox = New TextBox() + myTextBox.Text = "Enter text" + + ' Add child element to the DockPanel. + myDockPanel.Children.Add(myTextBox) + + ' Set the attached property value. + DockPanel.SetDock(myTextBox, Dock.Top) + ' + End Sub + + End Class + + ' + Public Class Aquarium + Inherits DependencyObject + + ' Register an attached dependency property with the specified + ' property name, property type, owner type, and property metadata. + Public Shared ReadOnly HasFishProperty As DependencyProperty = + DependencyProperty.RegisterAttached("HasFish", GetType(Boolean), GetType(Aquarium), + New FrameworkPropertyMetadata(defaultValue:=False, + flags:=FrameworkPropertyMetadataOptions.AffectsRender)) + + ' Declare a get accessor method. + Public Shared Function GetHasFish(target As UIElement) As Boolean + Return target.GetValue(HasFishProperty) + End Function + + ' Declare a set accessor method. + Public Shared Sub SetHasFish(target As UIElement, value As Boolean) + target.SetValue(HasFishProperty, value) + End Sub + + End Class + ' + +End Namespace diff --git a/dotnet-desktop-guide/net/wpf/toc.yml b/dotnet-desktop-guide/net/wpf/toc.yml index cc3d519..e28eb0d 100644 --- a/dotnet-desktop-guide/net/wpf/toc.yml +++ b/dotnet-desktop-guide/net/wpf/toc.yml @@ -88,6 +88,10 @@ items: href: properties/how-to-register-an-attached-property.md - name: Collection-type dependency properties href: properties/collection-type-dependency-properties.md + - name: Common tasks + items: + - name: Attached properties + href: properties/attached-properties-overview.md - name: Resources items: - name: Overview diff --git a/redirects_generator/definitions.json b/redirects_generator/definitions.json index 3ff61d6..f6cc73c 100644 --- a/redirects_generator/definitions.json +++ b/redirects_generator/definitions.json @@ -331,14 +331,19 @@ }, { "Redirect": "TwoWay", - "SourceUrl": "/dotnet/desktop/wpf/advanced/how-to-register-an-attached-property?view=netframeworkdesktop-4.8", - "TargetUrl": "/dotnet/desktop/wpf/properties/how-to-register-an-attached-property?view=netdesktop-5.0" + "SourceUrl": "/dotnet/desktop/wpf/advanced/attached-properties-overview?view=netframeworkdesktop-4.8", + "TargetUrl": "/dotnet/desktop/wpf/properties/attached-properties-overview?view=netdesktop-5.0" }, { "Redirect": "TwoWay", "SourceUrl": "/dotnet/desktop/wpf/advanced/collection-type-dependency-properties?view=netframeworkdesktop-4.8", "TargetUrl": "/dotnet/desktop/wpf/properties/collection-type-dependency-properties?view=netdesktop-5.0" }, + { + "Redirect": "TwoWay", + "SourceUrl": "/dotnet/desktop/wpf/advanced/how-to-register-an-attached-property?view=netframeworkdesktop-4.8", + "TargetUrl": "/dotnet/desktop/wpf/properties/how-to-register-an-attached-property?view=netdesktop-5.0" + }, // Systems - XAML { From cdf2334a602425c410a11df2eaaa8d2419aae388 Mon Sep 17 00:00:00 2001 From: Tris Shores <86677757+v-trisshores@users.noreply.github.com> Date: Fri, 22 Oct 2021 13:09:30 -0500 Subject: [PATCH 7/9] Add article, code projects, toc, and redirects (#1180) Co-authored-by: Andy (Steve) De George <67293991+adegeo@users.noreply.github.com> --- .openpublishing.redirection.json | 8 ++ .../how-to-implement-a-dependency-property.md | 36 ++++++ .../csharp/App.xaml | 9 ++ .../csharp/App.xaml.cs | 17 +++ .../csharp/AssemblyInfo.cs | 10 ++ .../csharp/CodeSampleCsharp.csproj | 24 ++++ .../csharp/MainWindow.xaml | 3 + .../csharp/MainWindow.xaml.cs | 30 +++++ .../csharp/Properties/Resources.Designer.cs | 63 +++++++++ .../csharp/Properties/Resources.resx | 120 ++++++++++++++++++ .../vb/Application.xaml | 9 ++ .../vb/Application.xaml.vb | 6 + .../vb/AssemblyInfo.vb | 11 ++ .../vb/CodeSampleVb.vbproj | 22 ++++ .../vb/MainWindow.xaml | 3 + .../vb/MainWindow.xaml.vb | 32 +++++ dotnet-desktop-guide/net/wpf/toc.yml | 10 +- redirects_generator/definitions.json | 5 + 18 files changed, 414 insertions(+), 4 deletions(-) create mode 100644 dotnet-desktop-guide/net/wpf/properties/how-to-implement-a-dependency-property.md create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/how-to-implement-a-dependency-property/csharp/App.xaml create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/how-to-implement-a-dependency-property/csharp/App.xaml.cs create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/how-to-implement-a-dependency-property/csharp/AssemblyInfo.cs create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/how-to-implement-a-dependency-property/csharp/CodeSampleCsharp.csproj create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/how-to-implement-a-dependency-property/csharp/MainWindow.xaml create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/how-to-implement-a-dependency-property/csharp/MainWindow.xaml.cs create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/how-to-implement-a-dependency-property/csharp/Properties/Resources.Designer.cs create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/how-to-implement-a-dependency-property/csharp/Properties/Resources.resx create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/how-to-implement-a-dependency-property/vb/Application.xaml create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/how-to-implement-a-dependency-property/vb/Application.xaml.vb create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/how-to-implement-a-dependency-property/vb/AssemblyInfo.vb create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/how-to-implement-a-dependency-property/vb/CodeSampleVb.vbproj create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/how-to-implement-a-dependency-property/vb/MainWindow.xaml create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/how-to-implement-a-dependency-property/vb/MainWindow.xaml.vb diff --git a/.openpublishing.redirection.json b/.openpublishing.redirection.json index 8c307c9..0d4f202 100644 --- a/.openpublishing.redirection.json +++ b/.openpublishing.redirection.json @@ -489,6 +489,14 @@ "source_path": "dotnet-desktop-guide/framework/wpf/properties/dependency-property-value-precedence.md", "redirect_url": "/dotnet/desktop/wpf/advanced/dependency-property-value-precedence?view=netframeworkdesktop-4.8" }, + { + "source_path": "dotnet-desktop-guide/net/wpf/advanced/how-to-implement-a-dependency-property.md", + "redirect_url": "/dotnet/desktop/wpf/properties/how-to-implement-a-dependency-property?view=netdesktop-5.0" + }, + { + "source_path": "dotnet-desktop-guide/framework/wpf/properties/how-to-implement-a-dependency-property.md", + "redirect_url": "/dotnet/desktop/wpf/advanced/how-to-implement-a-dependency-property?view=netframeworkdesktop-4.8" + }, { "source_path": "dotnet-desktop-guide/net/wpf/advanced/attached-properties-overview.md", "redirect_url": "/dotnet/desktop/wpf/properties/attached-properties-overview?view=netdesktop-5.0" diff --git a/dotnet-desktop-guide/net/wpf/properties/how-to-implement-a-dependency-property.md b/dotnet-desktop-guide/net/wpf/properties/how-to-implement-a-dependency-property.md new file mode 100644 index 0000000..afe80eb --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/how-to-implement-a-dependency-property.md @@ -0,0 +1,36 @@ +--- +title: "How to implement a dependency property" +description: "Define a dependency property in Windows Presentation Foundation (WPF), by backing a common language runtime property with a DependencyProperty field." +ms.date: "10/15/2021" +dev_langs: + - "csharp" + - "vb" +helpviewer_keywords: + - "dependency properties [WPF], backing properties with" + - "properties [WPF], backing with dependency properties" +--- + + +# How to implement a dependency property (WPF .NET) + +This article describes how to implement a dependency property by using a field to back a common language runtime (CLR) property. Dependency properties support several advanced Windows Presentation Foundation (WPF) property system features. These features include styles, data binding, inheritance, animation, and default values. If you want properties that you define to support those features, then implement your properties as a dependency property. + +## Example + +The following example shows how to register a dependency property, by calling the method. The `Register` method returns a instance called a *dependency property identifier*. The identifier is stored in a `static readonly` field, and holds the name and characteristics of a dependency property. + +The identifier field must follow the naming convention `Property`. For instance, if you register a dependency property with the name `Location`, then the identifier field should be named `LocationProperty`. If you fail to follow this naming pattern, then WPF designers might not report your property correctly, and aspects of the property system style application might not behave as expected. + +In the following example, the [name]() of the dependency property and its CLR accessor is `HasFish`, so the identifier field is named `HasFishProperty`. The dependency property type is and the owner type that registers the dependency property is `Aquarium`. + +You can specify default [metadata]() for a dependency property. This example sets a default value of `false` for the `HasFish` dependency property. + +:::code language="csharp" source="./snippets/how-to-implement-a-dependency-property/csharp/MainWindow.xaml.cs" id="DefineDependencyProperty"::: +:::code language="vb" source="./snippets/how-to-implement-a-dependency-property/vb/MainWindow.xaml.vb" id="DefineDependencyProperty"::: + +For more information about how and why to implement a dependency property, rather than just backing a CLR property with a private field, see [Dependency properties overview](dependency-properties-overview.md). + +## See also + +- [Dependency properties overview](dependency-properties-overview.md) +- [How-to topics](/dotnet/desktop/wpf/advanced/properties-how-to-topics?view=netframeworkdesktop-4.8&preserve-view=true) diff --git a/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-implement-a-dependency-property/csharp/App.xaml b/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-implement-a-dependency-property/csharp/App.xaml new file mode 100644 index 0000000..867d2f0 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-implement-a-dependency-property/csharp/App.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-implement-a-dependency-property/csharp/App.xaml.cs b/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-implement-a-dependency-property/csharp/App.xaml.cs new file mode 100644 index 0000000..3128552 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-implement-a-dependency-property/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/how-to-implement-a-dependency-property/csharp/AssemblyInfo.cs b/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-implement-a-dependency-property/csharp/AssemblyInfo.cs new file mode 100644 index 0000000..8b5504e --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-implement-a-dependency-property/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/how-to-implement-a-dependency-property/csharp/CodeSampleCsharp.csproj b/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-implement-a-dependency-property/csharp/CodeSampleCsharp.csproj new file mode 100644 index 0000000..8824b2f --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-implement-a-dependency-property/csharp/CodeSampleCsharp.csproj @@ -0,0 +1,24 @@ + + + + WinExe + net5.0-windows + true + + + + + True + True + Resources.resx + + + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + diff --git a/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-implement-a-dependency-property/csharp/MainWindow.xaml b/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-implement-a-dependency-property/csharp/MainWindow.xaml new file mode 100644 index 0000000..4746ae7 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-implement-a-dependency-property/csharp/MainWindow.xaml @@ -0,0 +1,3 @@ + diff --git a/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-implement-a-dependency-property/csharp/MainWindow.xaml.cs b/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-implement-a-dependency-property/csharp/MainWindow.xaml.cs new file mode 100644 index 0000000..d1bccdc --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-implement-a-dependency-property/csharp/MainWindow.xaml.cs @@ -0,0 +1,30 @@ +using System.Windows; + +namespace CodeSampleCsharp +{ + /// + /// Interaction logic for MainWindow.xaml. + /// + public partial class MainWindow : Window + { + public MainWindow() => InitializeComponent(); + } + + // + public class Aquarium : DependencyObject + { + public static readonly DependencyProperty HasFishProperty = + DependencyProperty.Register( + name: "HasFish", + propertyType: typeof(bool), + ownerType: typeof(Aquarium), + typeMetadata: new FrameworkPropertyMetadata(defaultValue: false)); + + public bool HasFish + { + get => (bool)GetValue(HasFishProperty); + set => SetValue(HasFishProperty, value); + } + } + // +} diff --git a/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-implement-a-dependency-property/csharp/Properties/Resources.Designer.cs b/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-implement-a-dependency-property/csharp/Properties/Resources.Designer.cs new file mode 100644 index 0000000..64552f9 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-implement-a-dependency-property/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/how-to-implement-a-dependency-property/csharp/Properties/Resources.resx b/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-implement-a-dependency-property/csharp/Properties/Resources.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-implement-a-dependency-property/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/how-to-implement-a-dependency-property/vb/Application.xaml b/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-implement-a-dependency-property/vb/Application.xaml new file mode 100644 index 0000000..f225972 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-implement-a-dependency-property/vb/Application.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-implement-a-dependency-property/vb/Application.xaml.vb b/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-implement-a-dependency-property/vb/Application.xaml.vb new file mode 100644 index 0000000..084cbe9 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-implement-a-dependency-property/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/how-to-implement-a-dependency-property/vb/AssemblyInfo.vb b/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-implement-a-dependency-property/vb/AssemblyInfo.vb new file mode 100644 index 0000000..025ee72 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-implement-a-dependency-property/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/how-to-implement-a-dependency-property/vb/CodeSampleVb.vbproj b/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-implement-a-dependency-property/vb/CodeSampleVb.vbproj new file mode 100644 index 0000000..c7ae1cc --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-implement-a-dependency-property/vb/CodeSampleVb.vbproj @@ -0,0 +1,22 @@ + + + + WinExe + net5.0-windows + CodeSampleVb + true + + + + + + + + + + + + + + + diff --git a/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-implement-a-dependency-property/vb/MainWindow.xaml b/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-implement-a-dependency-property/vb/MainWindow.xaml new file mode 100644 index 0000000..b255c55 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-implement-a-dependency-property/vb/MainWindow.xaml @@ -0,0 +1,3 @@ + diff --git a/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-implement-a-dependency-property/vb/MainWindow.xaml.vb b/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-implement-a-dependency-property/vb/MainWindow.xaml.vb new file mode 100644 index 0000000..cc7fcc7 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/how-to-implement-a-dependency-property/vb/MainWindow.xaml.vb @@ -0,0 +1,32 @@ +Namespace CodeSampleVb + Partial Public Class MainWindow + Inherits Window + + Public Sub New() + InitializeComponent() + End Sub + + ' + Public Class Aquarium + Inherits DependencyObject + + Public Shared ReadOnly HasFishProperty As DependencyProperty = + DependencyProperty.Register( + name:="HasFish", + propertyType:=GetType(Boolean), + ownerType:=GetType(Aquarium), + typeMetadata:=New FrameworkPropertyMetadata(defaultValue:=False)) + + Public Property HasFish As Boolean + Get + Return GetValue(HasFishProperty) + End Get + Set(value As Boolean) + SetValue(HasFishProperty, value) + End Set + End Property + + End Class + ' + End Class +End Namespace diff --git a/dotnet-desktop-guide/net/wpf/toc.yml b/dotnet-desktop-guide/net/wpf/toc.yml index e28eb0d..180eac4 100644 --- a/dotnet-desktop-guide/net/wpf/toc.yml +++ b/dotnet-desktop-guide/net/wpf/toc.yml @@ -84,14 +84,16 @@ items: href: properties/dependency-properties-overview.md - name: Dependency property value precedence href: properties/dependency-property-value-precedence.md - - name: Register an attached property - href: properties/how-to-register-an-attached-property.md + - name: Attached properties + href: properties/attached-properties-overview.md - name: Collection-type dependency properties href: properties/collection-type-dependency-properties.md - name: Common tasks items: - - name: Attached properties - href: properties/attached-properties-overview.md + - name: Implement a dependency property + href: properties/how-to-implement-a-dependency-property.md + - name: Register an attached property + href: properties/how-to-register-an-attached-property.md - name: Resources items: - name: Overview diff --git a/redirects_generator/definitions.json b/redirects_generator/definitions.json index f6cc73c..3dd161b 100644 --- a/redirects_generator/definitions.json +++ b/redirects_generator/definitions.json @@ -344,6 +344,11 @@ "SourceUrl": "/dotnet/desktop/wpf/advanced/how-to-register-an-attached-property?view=netframeworkdesktop-4.8", "TargetUrl": "/dotnet/desktop/wpf/properties/how-to-register-an-attached-property?view=netdesktop-5.0" }, + { + "Redirect": "TwoWay", + "SourceUrl": "/dotnet/desktop/wpf/advanced/how-to-implement-a-dependency-property?view=netframeworkdesktop-4.8", + "TargetUrl": "/dotnet/desktop/wpf/properties/how-to-implement-a-dependency-property?view=netdesktop-5.0" + }, // Systems - XAML { From 12375e0c406f8a31ad61f1e6d3eb8f57f6b1f889 Mon Sep 17 00:00:00 2001 From: Saisang Cai Date: Tue, 26 Oct 2021 15:51:44 +0000 Subject: [PATCH 8/9] Add metadata (#1185) * Add metadata * Update docfx.json * Update index.yml Co-authored-by: Andy (Steve) De George <67293991+adegeo@users.noreply.github.com> --- dotnet-desktop-guide/docfx.json | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/dotnet-desktop-guide/docfx.json b/dotnet-desktop-guide/docfx.json index 07366fe..b3db7ae 100644 --- a/dotnet-desktop-guide/docfx.json +++ b/dotnet-desktop-guide/docfx.json @@ -154,10 +154,15 @@ }, "ms.prod": { "framework/winforms/**/**.md": "dotnet-framework", + "framework/winforms/**/**.yml": "dotnet-framework", "framework/wpf/**/**.md": "dotnet-framework", + "framework/wpf/**/**.yml": "dotnet-framework", "net/winforms/**/**.md": "dotnet-desktop", + "net/winforms/**/**.yml": "dotnet-desktop", "net/wpf/**/**.md": "dotnet-desktop", - "xaml-services/**/*.md": "dotnet-desktop" + "net/wpf/**/**.yml": "dotnet-desktop", + "xaml-services/**/*.md": "dotnet-desktop", + "xaml-services/**/*.yml": "dotnet-desktop" }, "ms.topic": { "framework/winforms/**/**.md": "conceptual", From 95aaa17eb70ba91b4e1975958fc56aee168b2767 Mon Sep 17 00:00:00 2001 From: Tris Shores <86677757+v-trisshores@users.noreply.github.com> Date: Wed, 27 Oct 2021 12:50:15 -0500 Subject: [PATCH 9/9] Add redirect script (#1190) * Add redirect script * Update redirects_generator/redirect.bat Co-authored-by: Andy (Steve) De George <67293991+adegeo@users.noreply.github.com> * Delete temp file Co-authored-by: Andy (Steve) De George <67293991+adegeo@users.noreply.github.com> --- redirects_generator/redirect.bat | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 redirects_generator/redirect.bat diff --git a/redirects_generator/redirect.bat b/redirects_generator/redirect.bat new file mode 100644 index 0000000..76d6c7a --- /dev/null +++ b/redirects_generator/redirect.bat @@ -0,0 +1,3 @@ +dotnet run -- "..\.openpublishing.redirection.json" + +del .openpublishing.redirection.json \ No newline at end of file