diff --git a/.openpublishing.redirection.json b/.openpublishing.redirection.json index 958fc6daf3..2ea2fcc661 100644 --- a/.openpublishing.redirection.json +++ b/.openpublishing.redirection.json @@ -589,6 +589,14 @@ "source_path": "dotnet-desktop-guide/framework/wpf/properties/safe-constructor-patterns-for-dependencyobjects.md", "redirect_url": "/dotnet/desktop/wpf/advanced/safe-constructor-patterns-for-dependencyobjects?view=netframeworkdesktop-4.8" }, + { + "source_path": "dotnet-desktop-guide/net/wpf/advanced/property-value-inheritance.md", + "redirect_url": "/dotnet/desktop/wpf/properties/property-value-inheritance?view=netdesktop-6.0" + }, + { + "source_path": "dotnet-desktop-guide/framework/wpf/properties/property-value-inheritance.md", + "redirect_url": "/dotnet/desktop/wpf/advanced/property-value-inheritance?view=netframeworkdesktop-4.8" + }, { "source_path": "dotnet-desktop-guide/net/wpf/advanced/xaml-loading-and-dependency-properties.md", "redirect_url": "/dotnet/desktop/wpf/properties/xaml-loading-and-dependency-properties?view=netdesktop-6.0" diff --git a/dotnet-desktop-guide/net/wpf/properties/property-value-inheritance.md b/dotnet-desktop-guide/net/wpf/properties/property-value-inheritance.md new file mode 100644 index 0000000000..a7fd99d52f --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/property-value-inheritance.md @@ -0,0 +1,75 @@ +--- +title: "Dependency property value inheritance" +description: "Learn how dependency property value inheritance can be used to propagate property values in Windows Presentation Foundation (WPF)." +ms.date: "12/29/2021" +dev_langs: + - "csharp" + - "vb" +helpviewer_keywords: + - "inheritance [WPF], property values" + - "value inheritance [WPF]" + - "properties [WPF], value inheritance" +--- + + +# Property value inheritance (WPF .NET) + +Property value inheritance is a feature of the Windows Presentation Foundation (WPF) property system and applies to dependency properties. Property value inheritance lets child elements in a tree of elements obtain the value of a particular property from the nearest parent element. Since a parent element might also have obtained its property value through property value inheritance, the system potentially recurses back to the page root. + +The WPF property system doesn't enable property value inheritance by default, and value inheritance is inactive unless specifically enabled in dependency property [metadata](). Even with property value inheritance enabled, a child element will only inherit a property value in the absence of a higher [precedence](/dotnet/desktop/wpf/properties/dependency-property-value-precedence#dependency-property-setting-precedence-list) value. + +[!INCLUDE [desktop guide under construction](../../includes/desktop-guide-preview-note.md)] + +## Prerequisites + +The article assumes a basic knowledge of dependency properties, and that you've read [Dependency properties overview](dependency-properties-overview.md). To follow the examples in this article, it helps if you're familiar with Extensible Application Markup Language (XAML) and know how to write WPF applications. + +## Inheritance through an element tree + +Property value inheritance isn't the same concept as class inheritance in object-oriented programming, where derived classes inherit base class members. That kind of inheritance is also active in WPF, although in XAML the inherited base class properties are exposed as attributes of XAML elements that represent derived classes. + +Property value inheritance is the mechanism by which a dependency property value propagates from parent to child elements within a tree of elements that contain the property. In XAML markup, a tree of elements is visible as nested elements. + +The following example shows nested elements in XAML. WPF registers the dependency property on the class with property [metadata](framework-property-metadata.md) that enables property value [inheritance]() and sets the default value to `false`. The `AllowDrop` dependency property exists on , , and elements since they all derive from `UIElement`. Since the `AllowDrop` dependency property on `canvas1` is set to `true`, the descendant `stackPanel1` and `label1` elements inherit `true` as their `AllowDrop` value. + +:::code language="xaml" source="./snippets/property-value-inheritance/csharp/MainWindow.xaml" id="XamlElementTree"::: + +You can also create a tree of elements programmatically by adding element objects to the child element collection of another element object. At run time, property value inheritance operates on the resultant object tree. In the following example, `stackPanel2` is added to the [child collection]() of `canvas2`. Similarly, `label2` is added to the child collection of `stackPanel2`. Since the dependency property on `canvas2` is set to `true`, the descendant `stackPanel2` and `label2` elements inherit `true` as their `AllowDrop` value. + +:::code language="csharp" source="./snippets/property-value-inheritance/csharp/MainWindow.xaml.cs" id="CodeElementTree"::: +:::code language="vb" source="./snippets/property-value-inheritance/vb/MainWindow.xaml.vb" id="CodeElementTree"::: + +## Practical applications of property value inheritance + +Specific WPF dependency properties have value inheritance enabled by default, such as and . Typically, properties with value inheritance enabled by default are implemented on base UI element classes, so they exist on derived classes. For example, since `AllowDrop` is implemented on the base class, that dependency property also exists on every control derived from `UIElement`. WPF enables value inheritance on dependency properties for which it's convenient for a user to set the property value once on a parent element and have that property value propagate to descendant elements in the element tree. + +The property value inheritance model assigns property values, both inherited and uninherited, according to [dependency property value precedence](/dotnet/desktop/wpf/properties/dependency-property-value-precedence#dependency-property-setting-precedence-list). So, a parent element property value will only get applied to a child element, if the child element property doesn't have a higher precedence value, such as a locally set value, or a value obtained through styles, templates, or data binding. + +The dependency property sets the layout direction of text and child UI elements within a parent element. Typically, you would expect the flow direction of text and UI elements within a page to be consistent. Since value inheritance is enabled in the property [metadata]() of `FlowDirection`, a value need only be set once at the top of the element tree for a page. In the rare case where a mix of flow directions is intended for a page, a different flow direction can be set on an element in the tree by assigning a locally set value. The new flow direction will then propagate to descendant elements below that level. + +## Making a custom property inheritable + +You can make a custom dependency property inheritable by enabling the property in an instance of , and then registering your custom dependency property with that metadata instance. By default, `Inherits` is set to `false` in `FrameworkPropertyMetadata`. Making a property value inheritable affects performance, so only set `Inherits` to `true` if that feature is needed. + +When you register a dependency property with `Inherits` enabled in metadata, use the method as described in [Register an attached property](how-to-register-an-attached-property.md). Also, assign a default value to the property so that an inheritable value exists. You might also want to create a property wrapper with `get` and `set` accessors on the owner type, just as you would for a nonattached dependency property. That way you can set the property value using the property wrapper on an owner or derived type. The following example creates a dependency property named `IsTransparent`, with `Inherits` enabled and a default value of `false`. The example also includes a property wrapper with `get` and `set` accessors. + +:::code language="csharp" source="./snippets/property-value-inheritance/csharp/MainWindow.xaml.cs" id="RegisterAttachedPropertyWithValueInheritance"::: +:::code language="vb" source="./snippets/property-value-inheritance/vb/MainWindow.xaml.vb" id="RegisterAttachedPropertyWithValueInheritance"::: + +Attached properties are conceptually similar to global properties. You can check their value on any and get a valid result. The typical scenario for attached properties is to set property values on child elements, and that scenario is more effective if the property in question is implicitly present as an attached property on each element in the tree. + +## Inheriting property values across tree boundaries + +Property inheritance works by traversing a tree of elements. This tree is often parallel to the logical tree. However, whenever you include a WPF core-level object, such as a , in the markup that defines an element tree, you've created a discontinuous logical tree. A true logical tree doesn't conceptually extend through the `Brush`, because the logical tree is a WPF framework-level concept. You can use the helper methods of to analyze and view the extent of a logical tree. Property value inheritance is able to pass inherited values through a discontinuous logical tree, but only if the inheritable property was registered as an attached property and there isn't a deliberate inheritance-blocking boundary, such as a . + +> [!NOTE] +> Although property value inheritance might appear to work for nonattached dependency properties, the inheritance behavior for a nonattached property through some element boundaries in the runtime tree is undefined. Whenever you specify in property metadata, register your properties using . + +## See also + +- [Dependency property metadata](dependency-property-metadata.md) +- [Attached properties overview](attached-properties-overview.md) +- [Register an attached property](how-to-register-an-attached-property.md) +- [Custom dependency properties](custom-dependency-properties.md) +- [Dependency property value precedence](dependency-property-value-precedence.md) +- [Framework property metadata](framework-property-metadata.md) diff --git a/dotnet-desktop-guide/net/wpf/properties/snippets/property-value-inheritance/csharp/App.xaml.cs b/dotnet-desktop-guide/net/wpf/properties/snippets/property-value-inheritance/csharp/App.xaml.cs new file mode 100644 index 0000000000..31285520b3 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/property-value-inheritance/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/property-value-inheritance/csharp/AssemblyInfo.cs b/dotnet-desktop-guide/net/wpf/properties/snippets/property-value-inheritance/csharp/AssemblyInfo.cs new file mode 100644 index 0000000000..8b5504ecfb --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/property-value-inheritance/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/property-value-inheritance/csharp/CodeSampleCsharp.csproj b/dotnet-desktop-guide/net/wpf/properties/snippets/property-value-inheritance/csharp/CodeSampleCsharp.csproj new file mode 100644 index 0000000000..2a8c8c1918 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/property-value-inheritance/csharp/CodeSampleCsharp.csproj @@ -0,0 +1,10 @@ + + + + WinExe + net6.0-windows + true + en-US + + + diff --git a/dotnet-desktop-guide/net/wpf/properties/snippets/property-value-inheritance/csharp/MainWindow.xaml b/dotnet-desktop-guide/net/wpf/properties/snippets/property-value-inheritance/csharp/MainWindow.xaml new file mode 100644 index 0000000000..45e63b4979 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/property-value-inheritance/csharp/MainWindow.xaml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dotnet-desktop-guide/net/wpf/properties/snippets/property-value-inheritance/csharp/MainWindow.xaml.cs b/dotnet-desktop-guide/net/wpf/properties/snippets/property-value-inheritance/csharp/MainWindow.xaml.cs new file mode 100644 index 0000000000..feed7b5081 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/property-value-inheritance/csharp/MainWindow.xaml.cs @@ -0,0 +1,253 @@ +using System.Diagnostics; +using System.Windows; +using System.Windows.Controls; + +namespace CodeSampleCsharp +{ + /// + /// Interaction logic for MainWindow.xaml. + /// + public partial class MainWindow : Window + { + public MainWindow() + { + InitializeComponent(); + + // Code tests. + TestAllowDropInheritanceInXaml(); + TestAllowDropInheritanceInCode(); + TestIsTransparentInheritanceInCode(); + TestDependencyPropertyWrapper(); + } + + private void TestAllowDropInheritanceInXaml() + { + // Test enabled property value inheritance. + FrameworkPropertyMetadata fpm1 = (FrameworkPropertyMetadata) + AllowDropProperty.GetMetadata(typeof(Canvas)); + Debug.Assert(fpm1.Inherits == true); + Debug.Assert(canvas1.AllowDrop == true); + Debug.Assert(stackPanel1.AllowDrop == true); + Debug.Assert(label1.AllowDrop == true); + + // Test disabled property value inheritance. + FrameworkPropertyMetadata fpm11 = (FrameworkPropertyMetadata) + AllowDropProperty.GetMetadata(typeof(Canvas_AllowDropInheritDisabled)); + Debug.Assert(fpm11.Inherits == false); + Debug.Assert(canvas11.AllowDrop == true); + Debug.Assert(stackPanel11.AllowDrop == false); + Debug.Assert(label11.AllowDrop == false); + } + + private static void TestAllowDropInheritanceInCode() + { + // + Canvas canvas2 = new() + { + AllowDrop = true + }; + StackPanel stackPanel2 = new(); + Label label2 = new(); + canvas2.Children.Add(stackPanel2); + stackPanel2.Children.Add(label2); + // + + // Test enabled property value inheritance. + FrameworkPropertyMetadata fpm2 = (FrameworkPropertyMetadata) + AllowDropProperty.GetMetadata(typeof(Canvas)); + Debug.Assert(fpm2.Inherits == true); + Debug.Assert(canvas2.AllowDrop == true); + Debug.Assert(stackPanel2.AllowDrop == true); + Debug.Assert(label2.AllowDrop == true); + + // Test disabled property value inheritance. + Canvas_AllowDropInheritDisabled canvas3 = new() + { + AllowDrop = true + }; + StackPanel stackPanel3 = new(); + Label label3 = new(); + canvas3.Children.Add(stackPanel3); + stackPanel3.Children.Add(label3); + FrameworkPropertyMetadata fpm3 = (FrameworkPropertyMetadata) + AllowDropProperty.GetMetadata(typeof(Canvas_AllowDropInheritDisabled)); + Debug.Assert(fpm3.Inherits == false); + Debug.Assert(canvas3.AllowDrop == true); + Debug.Assert(stackPanel3.AllowDrop == false); + Debug.Assert(label3.AllowDrop == false); + } + + private static void TestIsTransparentInheritanceInCode() + { + // Test enabled property value inheritance. + Canvas_IsTransparentInheritEnabled myCanvas1 = new() + { + IsTransparent = true + }; + Canvas_IsTransparentInheritEnabled2 myCanvas2 = new(); + Canvas_IsTransparentInheritEnabled3 myCanvas3 = new(); + myCanvas1.Children.Add(myCanvas2); + myCanvas2.Children.Add(myCanvas3); + FrameworkPropertyMetadata fpm1 = (FrameworkPropertyMetadata)Canvas_IsTransparentInheritEnabled + .IsTransparentProperty.GetMetadata(typeof(Canvas_IsTransparentInheritEnabled)); + Debug.Assert(fpm1.Inherits == true); + Debug.Assert(myCanvas1.IsTransparent == true); + Debug.Assert(myCanvas2.IsTransparent == true); + Debug.Assert(myCanvas3.IsTransparent == true); + + // Test disabled property value inheritance. + Canvas_IsTransparentInheritDisabled myCanvas4 = new() + { + IsTransparent = true + }; + Canvas_IsTransparentInheritDisabled2 myCanvas5 = new(); + Canvas_IsTransparentInheritDisabled3 myCanvas6 = new(); + myCanvas4.Children.Add(myCanvas5); + myCanvas5.Children.Add(myCanvas6); + FrameworkPropertyMetadata fpm2 = (FrameworkPropertyMetadata)Canvas_IsTransparentInheritDisabled + .IsTransparentProperty.GetMetadata(typeof(Canvas_IsTransparentInheritDisabled)); + Debug.Assert(fpm2.Inherits == false); + Debug.Assert(myCanvas4.IsTransparent == true); + Debug.Assert(myCanvas5.IsTransparent == false); + Debug.Assert(myCanvas6.IsTransparent == false); + } + + private static void TestDependencyPropertyWrapper() + { + // Test Canvas_IsTransparentInheritEnabled. + Canvas_IsTransparentInheritEnabled myCanvas1 = new(); + Canvas_IsTransparentInheritEnabled2 myCanvas2 = new(); + Canvas_IsTransparentInheritEnabled3 myCanvas3 = new(); + // Test property wrapper. + myCanvas1.IsTransparent = true; + myCanvas2.IsTransparent = false; + myCanvas3.IsTransparent = true; + Debug.Assert(myCanvas1.IsTransparent == true); + Debug.Assert(myCanvas2.IsTransparent == false); + Debug.Assert(myCanvas3.IsTransparent == true); + // Test individual get/set accessors. + Canvas_IsTransparentInheritEnabled.SetIsTransparent(myCanvas1, false); + Canvas_IsTransparentInheritEnabled.SetIsTransparent(myCanvas2, true); + Canvas_IsTransparentInheritEnabled.SetIsTransparent(myCanvas3, false); + Debug.Assert(Canvas_IsTransparentInheritEnabled.GetIsTransparent(myCanvas1) == false); + Debug.Assert(Canvas_IsTransparentInheritEnabled.GetIsTransparent(myCanvas2) == true); + Debug.Assert(Canvas_IsTransparentInheritEnabled.GetIsTransparent(myCanvas3) == false); + + // Test Canvas_IsTransparentInheritDisabled. + Canvas_IsTransparentInheritDisabled myCanvas4 = new(); + Canvas_IsTransparentInheritDisabled2 myCanvas5 = new(); + Canvas_IsTransparentInheritDisabled3 myCanvas6 = new(); + // Test property wrapper. + myCanvas4.IsTransparent = true; + myCanvas5.IsTransparent = false; + myCanvas6.IsTransparent = true; + Debug.Assert(myCanvas4.IsTransparent == true); + Debug.Assert(myCanvas5.IsTransparent == false); + Debug.Assert(myCanvas6.IsTransparent == true); + // Test individual get/set accessors. + Canvas_IsTransparentInheritDisabled.SetIsTransparent(myCanvas4, false); + Canvas_IsTransparentInheritDisabled.SetIsTransparent(myCanvas5, true); + Canvas_IsTransparentInheritDisabled.SetIsTransparent(myCanvas6, false); + Debug.Assert(Canvas_IsTransparentInheritDisabled.GetIsTransparent(myCanvas4) == false); + Debug.Assert(Canvas_IsTransparentInheritDisabled.GetIsTransparent(myCanvas5) == true); + Debug.Assert(Canvas_IsTransparentInheritDisabled.GetIsTransparent(myCanvas6) == false); + } + } + + public class Canvas_AllowDropInheritDisabled : Canvas + { + static Canvas_AllowDropInheritDisabled() + { + // Disable property value inheritance in a new property metadata object. + FrameworkPropertyMetadata frameworkPropertyMetadata = new(); + frameworkPropertyMetadata.Inherits = false; + // Override existing property metadata. + AllowDropProperty.OverrideMetadata(typeof(Canvas_AllowDropInheritDisabled), frameworkPropertyMetadata); + } + } + + // + public class Canvas_IsTransparentInheritEnabled : Canvas + { + // Register an attached dependency property with the specified + // property name, property type, owner type, and property metadata + // (default value is 'false' and property value inheritance is enabled). + public static readonly DependencyProperty IsTransparentProperty = + DependencyProperty.RegisterAttached( + name: "IsTransparent", + propertyType: typeof(bool), + ownerType: typeof(Canvas_IsTransparentInheritEnabled), + defaultMetadata: new FrameworkPropertyMetadata( + defaultValue: false, + flags: FrameworkPropertyMetadataOptions.Inherits)); + + // Declare a get accessor method. + public static bool GetIsTransparent(Canvas element) + { + return (bool)element.GetValue(IsTransparentProperty); + } + + // Declare a set accessor method. + public static void SetIsTransparent(Canvas element, bool value) + { + element.SetValue(IsTransparentProperty, value); + } + + // For convenience, declare a property wrapper with get/set accessors. + public bool IsTransparent + { + get => (bool)GetValue(IsTransparentProperty); + set => SetValue(IsTransparentProperty, value); + } + } + // + + public class Canvas_IsTransparentInheritEnabled2 : Canvas_IsTransparentInheritEnabled + { + } + + public class Canvas_IsTransparentInheritEnabled3 : Canvas_IsTransparentInheritEnabled + { + } + + public class Canvas_IsTransparentInheritDisabled : Canvas + { + // Register an attached dependency property with the specified + // property name, property type, owner type, and property metadata + // (default value is 'false' and value inheritance is disabled). + public static readonly DependencyProperty IsTransparentProperty = + DependencyProperty.RegisterAttached( + name: "IsTransparent", + propertyType: typeof(bool), + ownerType: typeof(Canvas_IsTransparentInheritDisabled), + defaultMetadata: new FrameworkPropertyMetadata( + defaultValue: false)); + + // Declare a get accessor method. + public static bool GetIsTransparent(Canvas element) + { + return (bool)element.GetValue(IsTransparentProperty); + } + + // Declare a set accessor method. + public static void SetIsTransparent(Canvas element, bool value) + { + element.SetValue(IsTransparentProperty, value); + } + + // For convenience, declare a property wrapper with get/set accessors. + public bool IsTransparent + { + get => (bool)GetValue(IsTransparentProperty); + set => SetValue(IsTransparentProperty, value); + } + } + + public class Canvas_IsTransparentInheritDisabled2 : Canvas_IsTransparentInheritDisabled + { + } + + public class Canvas_IsTransparentInheritDisabled3 : Canvas_IsTransparentInheritDisabled + { + } +} diff --git a/dotnet-desktop-guide/net/wpf/properties/snippets/property-value-inheritance/csharp/Properties/Resources.Designer.cs b/dotnet-desktop-guide/net/wpf/properties/snippets/property-value-inheritance/csharp/Properties/Resources.Designer.cs new file mode 100644 index 0000000000..64552f96fd --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/property-value-inheritance/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/property-value-inheritance/csharp/Properties/Resources.resx b/dotnet-desktop-guide/net/wpf/properties/snippets/property-value-inheritance/csharp/Properties/Resources.resx new file mode 100644 index 0000000000..1af7de150c --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/property-value-inheritance/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/property-value-inheritance/csharp/app.xaml b/dotnet-desktop-guide/net/wpf/properties/snippets/property-value-inheritance/csharp/app.xaml new file mode 100644 index 0000000000..867d2f015f --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/property-value-inheritance/csharp/app.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/dotnet-desktop-guide/net/wpf/properties/snippets/property-value-inheritance/vb/Application.xaml b/dotnet-desktop-guide/net/wpf/properties/snippets/property-value-inheritance/vb/Application.xaml new file mode 100644 index 0000000000..db8a8eea71 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/property-value-inheritance/vb/Application.xaml @@ -0,0 +1,8 @@ + + + + + diff --git a/dotnet-desktop-guide/net/wpf/properties/snippets/property-value-inheritance/vb/Application.xaml.vb b/dotnet-desktop-guide/net/wpf/properties/snippets/property-value-inheritance/vb/Application.xaml.vb new file mode 100644 index 0000000000..084cbe917e --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/property-value-inheritance/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/property-value-inheritance/vb/AssemblyInfo.vb b/dotnet-desktop-guide/net/wpf/properties/snippets/property-value-inheritance/vb/AssemblyInfo.vb new file mode 100644 index 0000000000..07b608bb2d --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/property-value-inheritance/vb/AssemblyInfo.vb @@ -0,0 +1,9 @@ +'The ThemeInfo attribute describes where any theme specific and generic resource dictionaries can be found. +'1st parameter: where theme specific resource dictionaries are located +'(used if a resource is not found in the page, +' or application resource dictionaries) + +'2nd parameter: where the generic resource dictionary is located +'(used if a resource is not found in the page, +'app, and any theme specific resource dictionaries) + diff --git a/dotnet-desktop-guide/net/wpf/properties/snippets/property-value-inheritance/vb/CodeSampleVb.vbproj b/dotnet-desktop-guide/net/wpf/properties/snippets/property-value-inheritance/vb/CodeSampleVb.vbproj new file mode 100644 index 0000000000..a3f8743bb7 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/property-value-inheritance/vb/CodeSampleVb.vbproj @@ -0,0 +1,23 @@ + + + + WinExe + net6.0-windows + true + CodeSampleVb + en-US + + + + + + + + + + + + + + + diff --git a/dotnet-desktop-guide/net/wpf/properties/snippets/property-value-inheritance/vb/MainWindow.xaml b/dotnet-desktop-guide/net/wpf/properties/snippets/property-value-inheritance/vb/MainWindow.xaml new file mode 100644 index 0000000000..596ed9c1c1 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/property-value-inheritance/vb/MainWindow.xaml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dotnet-desktop-guide/net/wpf/properties/snippets/property-value-inheritance/vb/MainWindow.xaml.vb b/dotnet-desktop-guide/net/wpf/properties/snippets/property-value-inheritance/vb/MainWindow.xaml.vb new file mode 100644 index 0000000000..9fb3d402d9 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/property-value-inheritance/vb/MainWindow.xaml.vb @@ -0,0 +1,253 @@ +Namespace CodeSampleVb + Partial Public Class MainWindow + Inherits Window + + Public Sub New() + InitializeComponent() + + ' Code tests. + TestAllowDropInheritanceInXaml() + TestAllowDropInheritanceInCode() + TestIsTransparentInheritanceInCode() + TestDependencyPropertyWrapper() + End Sub + + Private Sub TestAllowDropInheritanceInXaml() + + ' Test enabled property value inheritance. + Dim fpm1 As FrameworkPropertyMetadata = + CType(AllowDropProperty. + GetMetadata(GetType(Canvas)), FrameworkPropertyMetadata) + Debug.Assert(fpm1.[Inherits] = True) + Debug.Assert(canvas1.AllowDrop = True) + Debug.Assert(stackPanel1.AllowDrop = True) + Debug.Assert(label1.AllowDrop = True) + + ' Test disabled property value inheritance. + Dim fpm11 As FrameworkPropertyMetadata = + CType(AllowDropProperty. + GetMetadata(GetType(Canvas_AllowDropInheritDisabled)), FrameworkPropertyMetadata) + Debug.Assert(fpm11.[Inherits] = False) + ' Debug.Assert(canvas11.AllowDrop = True) + Debug.Assert(stackPanel11.AllowDrop = False) + Debug.Assert(label11.AllowDrop = False) + End Sub + + Private Shared Sub TestAllowDropInheritanceInCode() + + ' + Dim canvas2 As New Canvas With { + .AllowDrop = True + } + Dim stackPanel2 As New StackPanel() + Dim label2 As New Label() + canvas2.Children.Add(stackPanel2) + stackPanel2.Children.Add(label2) + ' + + ' Test enabled property value inheritance. + Dim fpm2 As FrameworkPropertyMetadata = + CType(AllowDropProperty. + GetMetadata(GetType(Canvas)), FrameworkPropertyMetadata) + Debug.Assert(fpm2.[Inherits] = True) + Debug.Assert(canvas2.AllowDrop = True) + Debug.Assert(stackPanel2.AllowDrop = True) + Debug.Assert(label2.AllowDrop = True) + + ' Test disabled property value inheritance. + Dim canvas3 As New Canvas_AllowDropInheritDisabled With { + .AllowDrop = True + } + Dim stackPanel3 As New StackPanel() + Dim label3 As New Label() + canvas3.Children.Add(stackPanel3) + stackPanel3.Children.Add(label3) + Dim fpm3 As FrameworkPropertyMetadata = + CType(AllowDropProperty. + GetMetadata(GetType(Canvas_AllowDropInheritDisabled)), FrameworkPropertyMetadata) + Debug.Assert(fpm3.[Inherits] = False) + Debug.Assert(canvas3.AllowDrop = True) + Debug.Assert(stackPanel3.AllowDrop = False) + Debug.Assert(label3.AllowDrop = False) + + End Sub + + Private Shared Sub TestIsTransparentInheritanceInCode() + + ' Test enabled property value inheritance. + Dim myCanvas1 As New Canvas_IsTransparentInheritEnabled With { + .IsTransparent = True + } + Dim myCanvas2 As New Canvas_IsTransparentInheritEnabled2() + Dim myCanvas3 As New Canvas_IsTransparentInheritEnabled3() + myCanvas1.Children.Add(myCanvas2) + myCanvas2.Children.Add(myCanvas3) + Dim fpm1 As FrameworkPropertyMetadata = + CType(Canvas_IsTransparentInheritEnabled.IsTransparentProperty. + GetMetadata(GetType(Canvas_IsTransparentInheritEnabled)), FrameworkPropertyMetadata) + Debug.Assert(fpm1.[Inherits] = True) + Debug.Assert(myCanvas1.IsTransparent = True) + Debug.Assert(myCanvas2.IsTransparent = True) + Debug.Assert(myCanvas3.IsTransparent = True) + + ' Test disabled property value inheritance. + Dim myCanvas4 As New Canvas_IsTransparentInheritDisabled With { + .IsTransparent = True + } + Dim myCanvas5 As New Canvas_IsTransparentInheritDisabled2() + Dim myCanvas6 As New Canvas_IsTransparentInheritDisabled3() + myCanvas4.Children.Add(myCanvas5) + myCanvas5.Children.Add(myCanvas6) + Dim fpm2 As FrameworkPropertyMetadata = + CType(Canvas_IsTransparentInheritDisabled.IsTransparentProperty. + GetMetadata(GetType(Canvas_IsTransparentInheritDisabled)), FrameworkPropertyMetadata) + Debug.Assert(fpm2.[Inherits] = False) + Debug.Assert(myCanvas4.IsTransparent = True) + Debug.Assert(myCanvas5.IsTransparent = False) + Debug.Assert(myCanvas6.IsTransparent = False) + + End Sub + + Private Shared Sub TestDependencyPropertyWrapper() + + ' Test Canvas_IsTransparentInheritEnabled. + Dim myCanvas1 As New Canvas_IsTransparentInheritEnabled() + Dim myCanvas2 As New Canvas_IsTransparentInheritEnabled2() + Dim myCanvas3 As New Canvas_IsTransparentInheritEnabled3() + ' Test property wrapper. + myCanvas1.IsTransparent = True + myCanvas2.IsTransparent = False + myCanvas3.IsTransparent = True + Debug.Assert(myCanvas1.IsTransparent = True) + Debug.Assert(myCanvas2.IsTransparent = False) + Debug.Assert(myCanvas3.IsTransparent = True) + ' Test individual get/set accessors. + Canvas_IsTransparentInheritEnabled.SetIsTransparent(myCanvas1, False) + Canvas_IsTransparentInheritEnabled.SetIsTransparent(myCanvas2, True) + Canvas_IsTransparentInheritEnabled.SetIsTransparent(myCanvas3, False) + Debug.Assert(Canvas_IsTransparentInheritEnabled.GetIsTransparent(myCanvas1) = False) + Debug.Assert(Canvas_IsTransparentInheritEnabled.GetIsTransparent(myCanvas2) = True) + Debug.Assert(Canvas_IsTransparentInheritEnabled.GetIsTransparent(myCanvas3) = False) + + ' Test Canvas_IsTransparentInheritDisabled. + Dim myCanvas4 As New Canvas_IsTransparentInheritDisabled() + Dim myCanvas5 As New Canvas_IsTransparentInheritDisabled2() + Dim myCanvas6 As New Canvas_IsTransparentInheritDisabled3() + ' Test property wrapper. + myCanvas4.IsTransparent = True + myCanvas5.IsTransparent = False + myCanvas6.IsTransparent = True + Debug.Assert(myCanvas4.IsTransparent = True) + Debug.Assert(myCanvas5.IsTransparent = False) + Debug.Assert(myCanvas6.IsTransparent = True) + ' Test individual get/set accessors. + Canvas_IsTransparentInheritDisabled.SetIsTransparent(myCanvas4, False) + Canvas_IsTransparentInheritDisabled.SetIsTransparent(myCanvas5, True) + Canvas_IsTransparentInheritDisabled.SetIsTransparent(myCanvas6, False) + Debug.Assert(Canvas_IsTransparentInheritDisabled.GetIsTransparent(myCanvas4) = False) + Debug.Assert(Canvas_IsTransparentInheritDisabled.GetIsTransparent(myCanvas5) = True) + Debug.Assert(Canvas_IsTransparentInheritDisabled.GetIsTransparent(myCanvas6) = False) + + End Sub + End Class + + Public Class Canvas_AllowDropInheritDisabled + Inherits Canvas + Shared Sub New() + ' Disable property value inheritance in a new property metadata object. + Dim frameworkPropertyMetadata As New FrameworkPropertyMetadata With { + .Inherits = False + } + ' Override existing property metadata. + AllowDropProperty.OverrideMetadata(GetType(Canvas_AllowDropInheritDisabled), frameworkPropertyMetadata) + End Sub + End Class + + ' + Public Class Canvas_IsTransparentInheritEnabled + Inherits Canvas + + ' Register an attached dependency property with the specified + ' property name, property type, owner type, and property metadata + ' (default value is 'false' and property value inheritance is enabled). + Public Shared ReadOnly IsTransparentProperty As DependencyProperty = + DependencyProperty.RegisterAttached( + name:="IsTransparent", + propertyType:=GetType(Boolean), + ownerType:=GetType(Canvas_IsTransparentInheritEnabled), + defaultMetadata:=New FrameworkPropertyMetadata( + defaultValue:=False, + flags:=FrameworkPropertyMetadataOptions.[Inherits])) + + ' Declare a get accessor method. + Public Shared Function GetIsTransparent(element As Canvas) As Boolean + Return element.GetValue(IsTransparentProperty) + End Function + + ' Declare a set accessor method. + Public Shared Sub SetIsTransparent(element As Canvas, value As Boolean) + element.SetValue(IsTransparentProperty, value) + End Sub + + ' For convenience, declare a property wrapper with get/set accessors. + Public Property IsTransparent As Boolean + Get + Return GetValue(IsTransparentProperty) + End Get + Set(value As Boolean) + SetValue(IsTransparentProperty, value) + End Set + End Property + End Class + ' + + Public Class Canvas_IsTransparentInheritEnabled2 + Inherits Canvas_IsTransparentInheritEnabled + End Class + + Public Class Canvas_IsTransparentInheritEnabled3 + Inherits Canvas_IsTransparentInheritEnabled + End Class + + Public Class Canvas_IsTransparentInheritDisabled + Inherits Canvas + + ' Register an attached dependency property with the specified + ' property name, property type, owner type, and property metadata + ' (default value is 'false' and property value inheritance is disabled). + Public Shared ReadOnly IsTransparentProperty As DependencyProperty = + DependencyProperty.RegisterAttached( + name:="IsTransparent", + propertyType:=GetType(Boolean), + ownerType:=GetType(Canvas_IsTransparentInheritDisabled), + defaultMetadata:=New FrameworkPropertyMetadata(defaultValue:=False)) + + ' Declare a get accessor method. + Public Shared Function GetIsTransparent(element As Canvas) As Boolean + Return element.GetValue(IsTransparentProperty) + End Function + + ' Declare a set accessor method. + Public Shared Sub SetIsTransparent(element As Canvas, value As Boolean) + element.SetValue(IsTransparentProperty, value) + End Sub + + ' For convenience, declare a property wrapper with get/set accessors. + Public Property IsTransparent As Boolean + Get + Return GetValue(IsTransparentProperty) + End Get + Set(value As Boolean) + SetValue(IsTransparentProperty, value) + End Set + End Property + End Class + + Public Class Canvas_IsTransparentInheritDisabled2 + Inherits Canvas_IsTransparentInheritDisabled + End Class + + Public Class Canvas_IsTransparentInheritDisabled3 + Inherits Canvas_IsTransparentInheritDisabled + End Class +End Namespace diff --git a/dotnet-desktop-guide/net/wpf/toc.yml b/dotnet-desktop-guide/net/wpf/toc.yml index 411c7084b8..9e6946542f 100644 --- a/dotnet-desktop-guide/net/wpf/toc.yml +++ b/dotnet-desktop-guide/net/wpf/toc.yml @@ -102,6 +102,8 @@ items: href: properties/dependency-property-security.md - name: Safe constructor patterns for DependencyObjects href: properties/safe-constructor-patterns-for-dependencyobjects.md + - name: Property value inheritance + href: properties/property-value-inheritance.md - name: XAML loading and dependency properties href: properties/xaml-loading-and-dependency-properties.md - name: Common tasks diff --git a/redirects_generator/definitions.json b/redirects_generator/definitions.json index 4172523fdb..df0732df01 100644 --- a/redirects_generator/definitions.json +++ b/redirects_generator/definitions.json @@ -395,6 +395,10 @@ "SourceUrl": "/dotnet/desktop/wpf/advanced/safe-constructor-patterns-for-dependencyobjects?view=netframeworkdesktop-4.8", "TargetUrl": "/dotnet/desktop/wpf/properties/safe-constructor-patterns-for-dependencyobjects?view=netdesktop-6.0" }, + { + "SourceUrl": "/dotnet/desktop/wpf/advanced/property-value-inheritance?view=netframeworkdesktop-4.8", + "TargetUrl": "/dotnet/desktop/wpf/properties/property-value-inheritance?view=netdesktop-6.0" + }, { "SourceUrl": "/dotnet/desktop/wpf/advanced/xaml-loading-and-dependency-properties?view=netframeworkdesktop-4.8", "TargetUrl": "/dotnet/desktop/wpf/properties/xaml-loading-and-dependency-properties?view=netdesktop-6.0"