From 5eff6608b9b53e356ac9ddc636e630aeb6b40971 Mon Sep 17 00:00:00 2001 From: Tris Shores <86677757+v-trisshores@users.noreply.github.com> Date: Wed, 1 Dec 2021 17:50:53 -0600 Subject: [PATCH] Content update - Read-only dependency properties (user story 1878471) (#1230) * Improve collection-type dp snippets that are readonly. * Add article, snippets, toc, and redirects * Minor edit * Update target framework to .NET 6.0 --- .openpublishing.redirection.json | 8 ++ .../read-only-dependency-properties.md | 67 ++++++++++ .../csharp/MainWindow.xaml | 7 +- .../csharp/MainWindow.xaml.cs | 30 ++--- .../vb/MainWindow.xaml | 7 +- .../vb/MainWindow.xaml.vb | 34 +++-- .../csharp/App.xaml.cs | 17 +++ .../csharp/AssemblyInfo.cs | 10 ++ .../csharp/CodeSampleCsharp.csproj | 24 ++++ .../csharp/MainWindow.xaml | 12 ++ .../csharp/MainWindow.xaml.cs | 38 ++++++ .../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 | 12 ++ .../vb/MainWindow.xaml.vb | 47 +++++++ dotnet-desktop-guide/net/wpf/toc.yml | 2 + redirects_generator/definitions.json | 5 + 22 files changed, 520 insertions(+), 40 deletions(-) create mode 100644 dotnet-desktop-guide/net/wpf/properties/read-only-dependency-properties.md create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/read-only-dependency-properties/csharp/App.xaml.cs create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/read-only-dependency-properties/csharp/AssemblyInfo.cs create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/read-only-dependency-properties/csharp/CodeSampleCsharp.csproj create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/read-only-dependency-properties/csharp/MainWindow.xaml create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/read-only-dependency-properties/csharp/MainWindow.xaml.cs create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/read-only-dependency-properties/csharp/Properties/Resources.Designer.cs create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/read-only-dependency-properties/csharp/Properties/Resources.resx create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/read-only-dependency-properties/csharp/app.xaml create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/read-only-dependency-properties/vb/Application.xaml create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/read-only-dependency-properties/vb/Application.xaml.vb create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/read-only-dependency-properties/vb/AssemblyInfo.vb create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/read-only-dependency-properties/vb/CodeSampleVb.vbproj create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/read-only-dependency-properties/vb/MainWindow.xaml create mode 100644 dotnet-desktop-guide/net/wpf/properties/snippets/read-only-dependency-properties/vb/MainWindow.xaml.vb diff --git a/.openpublishing.redirection.json b/.openpublishing.redirection.json index e52d220..02c81da 100644 --- a/.openpublishing.redirection.json +++ b/.openpublishing.redirection.json @@ -556,6 +556,14 @@ { "source_path": "dotnet-desktop-guide/framework/wpf/properties/dependency-property-callbacks-and-validation.md", "redirect_url": "/dotnet/desktop/wpf/advanced/dependency-property-callbacks-and-validation?view=netframeworkdesktop-4.8" + }, + { + "source_path": "dotnet-desktop-guide/net/wpf/advanced/read-only-dependency-properties.md", + "redirect_url": "/dotnet/desktop/wpf/properties/read-only-dependency-properties?view=netdesktop-6.0" + }, + { + "source_path": "dotnet-desktop-guide/framework/wpf/properties/read-only-dependency-properties.md", + "redirect_url": "/dotnet/desktop/wpf/advanced/read-only-dependency-properties?view=netframeworkdesktop-4.8" } ] } diff --git a/dotnet-desktop-guide/net/wpf/properties/read-only-dependency-properties.md b/dotnet-desktop-guide/net/wpf/properties/read-only-dependency-properties.md new file mode 100644 index 0000000..238ad42 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/read-only-dependency-properties.md @@ -0,0 +1,67 @@ +--- +title: "Read-only dependency properties" +description: Learn about dependency properties in Windows Presentation Foundation (WPF) and how to create a read-only dependency property. +ms.date: "11/29/2021" +dev_langs: + - "csharp" + - "vb" +helpviewer_keywords: + - "dependency properties [WPF], read-only" + - "read-only dependency properties [WPF]" +--- + + +# Read-only dependency properties (WPF .NET) + +You can use read-only dependency properties to prevent property values being set from outside your code. This article discusses existing read-only dependency properties and the scenarios and techniques for creating a custom read-only dependency property. + +[!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. + +## Existing read-only dependency properties + +Read-only dependency properties typically report state, and shouldn't be modifiable through a `public` accessor. For example, the Windows Presentation Foundation (WPF) framework implements the property as read-only because its value should only be determined by mouse input. If `IsMouseOver` allowed other inputs, its value might become inconsistent with mouse input. Though not settable through a `public` accessor, many existing read-only dependency properties have values determined by multiple inputs. + +## Uses of read-only dependency properties + +Read-only dependency properties aren't applicable in several scenarios where dependency properties normally offer a solution. Non-applicable scenarios include data binding, applying a style to a value, validation, animation, and inheritance. However, a read-only dependency property can be used as a property trigger in a style. For example, is commonly used to trigger changes to the background, foreground, or other visible property of a control when the mouse is over it. The WPF property system detects and reports changes in read-only dependency properties, thus supporting property trigger functionality. Read-only dependency properties are also useful when implementing a collection-type dependency property where only the collection elements need to be writeable, not the collection object itself. For more information, see [Collection-type dependency properties](collection-type-dependency-properties.md). + +> [!NOTE] +> Only dependency properties, not regular common language runtime properties, can be used as property triggers in a style. + +## Creating custom read-only dependency properties + +Before creating a dependency property that's read-only, check the [non-applicable scenarios](#uses-of-read-only-dependency-properties). + +The process of creating a read-only dependency property is in many ways similar to creating read-write dependency properties, with these distinctions: + +- When registering your read-only property, call instead of . + +- When implementing the CLR property wrapper, make sure it doesn't have a public `set` accessor. + +- `RegisterReadOnly` returns instead of . Store the `DependencyPropertyKey` in a nonpublic class member. + +You can determine the value of your read-only dependency property using whatever logic you choose. The recommended way to set the property value, either initially or as part of runtime logic, is to use the overload of that accepts a parameter of type `DependencyPropertyKey`. Using `SetValue` is preferable to circumventing the property system and setting the backing field directly. + +How and where you set the value of a read-only dependency property within your application will affect the access level you assign to the class member that stores the `DependencyPropertyKey`. If you only set the property value from within the class that registers the dependency property, you can use a `private` access modifier. For scenarios where the values of dependency properties affect each other, you can use paired and callbacks to trigger value changes. For more information, see [Dependency property metadata](dependency-property-metadata.md). + +If you need to change the value of a read-only dependency property from outside the class that registers it, you can use an `internal` access modifier for the `DependencyPropertyKey`. For example, you might call `SetValue` from an event handler in the same assembly. The following example defines an Aquarium class that calls `RegisterReadOnly` to create the read-only dependency property `FishCount`. The `DependencyPropertyKey` is assigned to an `internal static readonly` field, so that code in the same assembly can change the read-only dependency property value. + +:::code language="csharp" source="./snippets/read-only-dependency-properties/csharp/MainWindow.xaml.cs" id="RegisterReadOnlyDependencyProperty"::: +:::code language="vb" source="./snippets/read-only-dependency-properties/vb/MainWindow.xaml.vb" id="RegisterReadOnlyDependencyProperty"::: + +Because the WPF property system doesn't propagate the outside your code, read-only dependency properties have better write security than read-write dependency properties. Use a read-only dependency property when you want to limit write-access to those who have a reference to the `DependencyPropertyKey`. + +In contrast, the dependency property identifier for read-write dependency properties is accessible through the property system, no matter what access modifier you assign it. For more information, see [Dependency property security](/dotnet/desktop/wpf/advanced/dependency-property-security?view=netframeworkdesktop-4.8&preserve-view=true). + +## See also + +- [Dependency properties overview](dependency-properties-overview.md) +- [Implement a Dependency property](how-to-implement-a-dependency-property.md) +- [Custom dependency properties](custom-dependency-properties.md) +- [Collection-type dependency properties](collection-type-dependency-properties.md) +- [Dependency property security](/dotnet/desktop/wpf/advanced/dependency-property-security?view=netframeworkdesktop-4.8&preserve-view=true) +- [Styles and templates in WPF](/dotnet/desktop/wpf/controls/styles-templates-overview) 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 index e3a44de..ea238ef 100644 --- 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 @@ -1,11 +1,12 @@  + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + Title="Collection-Type Dependency Properties" Height="100" Width="500"> - + + 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 index ab9914b..49d4a16 100644 --- 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 @@ -16,10 +16,15 @@ namespace CodeSampleCsharp 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"); + $"aquarium1 contains {aquarium1.AquariumContents.Count} fish\r\n" + + $"aquarium2 contains {aquarium2.AquariumContents.Count} fish"); } // + + private void InitializeFreezableAquariums(object sender, RoutedEventArgs e) + { + FreezableCollectionAquarium.InitializeAquariums(); + } } // @@ -36,16 +41,12 @@ namespace CodeSampleCsharp //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. + // Declare a public get accessor. public List AquariumContents => - (List)GetValue(AquariumContentsProperty); + (List)GetValue(s_aquariumContentsPropertyKey.DependencyProperty); } public class Fish : FrameworkElement { } @@ -61,8 +62,8 @@ namespace CodeSampleCsharp 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"); + $"aquarium1 contains {aquarium1.AquariumContents.Count} fish\r\n" + + $"aquarium2 contains {aquarium2.AquariumContents.Count} fish"); } // @@ -81,7 +82,7 @@ namespace CodeSampleCsharp // Set the default collection value in a class constructor. public Aquarium() => SetValue(AquariumContentsProperty, new List()); - // Declare a read-write property. + // Declare public get and set accessors. public List AquariumContents { get => (List)GetValue(AquariumContentsProperty); @@ -102,8 +103,8 @@ namespace CodeSampleCsharp 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"); + $"FreezableCollection aquarium1 contains {aquarium1.AquariumContents.Count} fish\r\n" + + $"FreezableCollection aquarium2 contains {aquarium2.AquariumContents.Count} fish"); } // @@ -126,11 +127,10 @@ namespace CodeSampleCsharp // Set the default collection value in a class constructor. public Aquarium() => SetValue(s_aquariumContentsPropertyKey, new FreezableCollection()); - // Declare a read-only property. + // Declare a public get accessor. public FreezableCollection AquariumContents => (FreezableCollection)GetValue(AquariumContentsProperty); } - // public class Fish : FrameworkElement { } 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 index 2080a2f..0cf6a98 100644 --- 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 @@ -1,11 +1,12 @@  + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + Title="Collection-Type Dependency Properties" Height="100" Width="500"> - + + 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 index 4743b19..7fc8f23 100644 --- 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 @@ -16,11 +16,15 @@ 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") + MessageBox.Show($"aquarium1 contains {aquarium1.AquariumContents.Count} fish{Environment.NewLine}" + + $"aquarium2 contains {aquarium2.AquariumContents.Count} fish") End Sub ' + Private Sub InitializeFreezableAquariums(sender As Object, e As RoutedEventArgs) + FreezableCollectionAquarium.InitializeAquariums() + End Sub + End Class ' @@ -37,19 +41,15 @@ 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. + ' Declare a public get accessor. Public ReadOnly Property AquariumContents As List(Of FrameworkElement) Get - Return CType(GetValue(AquariumContentsProperty), List(Of FrameworkElement)) + Return CType(GetValue(s_aquariumContentsPropertyKey.DependencyProperty), List(Of FrameworkElement)) End Get End Property End Class @@ -67,8 +67,8 @@ 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") + MessageBox.Show($"aquarium1 contains {aquarium1.AquariumContents.Count} fish{Environment.NewLine}" + + $"aquarium2 contains {aquarium2.AquariumContents.Count} fish") End Sub ' @@ -89,7 +89,7 @@ SetValue(AquariumContentsProperty, New List(Of FrameworkElement)()) End Sub - ' Declare a read-write property. + ' Declare public get and set accessors. Public Property AquariumContents As List(Of FrameworkElement) Get Return CType(GetValue(AquariumContentsProperty), List(Of FrameworkElement)) @@ -114,8 +114,8 @@ 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") + MessageBox.Show($"FreezableCollection aquarium1 contains {aquarium1.AquariumContents.Count} fish{Environment.NewLine}" + + $"FreezableCollection aquarium2 contains {aquarium2.AquariumContents.Count} fish") End Sub ' @@ -131,19 +131,15 @@ 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. + ' Declare a public get accessor. Public ReadOnly Property AquariumContents As FreezableCollection(Of FrameworkElement) Get - Return CType(GetValue(AquariumContentsProperty), FreezableCollection(Of FrameworkElement)) + Return CType(GetValue(s_aquariumContentsPropertyKey.DependencyProperty), FreezableCollection(Of FrameworkElement)) End Get End Property End Class diff --git a/dotnet-desktop-guide/net/wpf/properties/snippets/read-only-dependency-properties/csharp/App.xaml.cs b/dotnet-desktop-guide/net/wpf/properties/snippets/read-only-dependency-properties/csharp/App.xaml.cs new file mode 100644 index 0000000..3128552 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/read-only-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/read-only-dependency-properties/csharp/AssemblyInfo.cs b/dotnet-desktop-guide/net/wpf/properties/snippets/read-only-dependency-properties/csharp/AssemblyInfo.cs new file mode 100644 index 0000000..8b5504e --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/read-only-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/read-only-dependency-properties/csharp/CodeSampleCsharp.csproj b/dotnet-desktop-guide/net/wpf/properties/snippets/read-only-dependency-properties/csharp/CodeSampleCsharp.csproj new file mode 100644 index 0000000..22d78ee --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/read-only-dependency-properties/csharp/CodeSampleCsharp.csproj @@ -0,0 +1,24 @@ + + + + WinExe + net6.0-windows + true + + + + + True + True + Resources.resx + + + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + diff --git a/dotnet-desktop-guide/net/wpf/properties/snippets/read-only-dependency-properties/csharp/MainWindow.xaml b/dotnet-desktop-guide/net/wpf/properties/snippets/read-only-dependency-properties/csharp/MainWindow.xaml new file mode 100644 index 0000000..0c1f59a --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/read-only-dependency-properties/csharp/MainWindow.xaml @@ -0,0 +1,12 @@ + + + + + + + diff --git a/dotnet-desktop-guide/net/wpf/properties/snippets/read-only-dependency-properties/csharp/MainWindow.xaml.cs b/dotnet-desktop-guide/net/wpf/properties/snippets/read-only-dependency-properties/csharp/MainWindow.xaml.cs new file mode 100644 index 0000000..2edcbde --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/read-only-dependency-properties/csharp/MainWindow.xaml.cs @@ -0,0 +1,38 @@ +using System.Windows; + +namespace CodeSampleCsharp +{ + /// + /// Interaction logic for MainWindow.xaml. + /// + public partial class MainWindow : Window + { + readonly Aquarium _aquarium = new(); + + private void Button_Click(object sender, RoutedEventArgs e) + { + // Test setting a value. + _aquarium.SetValue(Aquarium.FishCountPropertyKey, _aquarium.FishCount + 1); + lblFishCount.Content = $"Aquarium fish count: {_aquarium.FishCount}"; + } + } + + // + public class Aquarium : DependencyObject + { + // Register a dependency property with the specified property name, + // property type, owner type, and property metadata. + // Assign DependencyPropertyKey to a nonpublic field. + internal static readonly DependencyPropertyKey FishCountPropertyKey = + DependencyProperty.RegisterReadOnly( + name: "FishCount", + propertyType: typeof(int), + ownerType: typeof(Aquarium), + typeMetadata: new FrameworkPropertyMetadata()); + + // Declare a public get accessor. + public int FishCount => + (int)GetValue(FishCountPropertyKey.DependencyProperty); + } + // +} diff --git a/dotnet-desktop-guide/net/wpf/properties/snippets/read-only-dependency-properties/csharp/Properties/Resources.Designer.cs b/dotnet-desktop-guide/net/wpf/properties/snippets/read-only-dependency-properties/csharp/Properties/Resources.Designer.cs new file mode 100644 index 0000000..64552f9 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/read-only-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/read-only-dependency-properties/csharp/Properties/Resources.resx b/dotnet-desktop-guide/net/wpf/properties/snippets/read-only-dependency-properties/csharp/Properties/Resources.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/read-only-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/read-only-dependency-properties/csharp/app.xaml b/dotnet-desktop-guide/net/wpf/properties/snippets/read-only-dependency-properties/csharp/app.xaml new file mode 100644 index 0000000..867d2f0 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/read-only-dependency-properties/csharp/app.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/dotnet-desktop-guide/net/wpf/properties/snippets/read-only-dependency-properties/vb/Application.xaml b/dotnet-desktop-guide/net/wpf/properties/snippets/read-only-dependency-properties/vb/Application.xaml new file mode 100644 index 0000000..f225972 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/read-only-dependency-properties/vb/Application.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/dotnet-desktop-guide/net/wpf/properties/snippets/read-only-dependency-properties/vb/Application.xaml.vb b/dotnet-desktop-guide/net/wpf/properties/snippets/read-only-dependency-properties/vb/Application.xaml.vb new file mode 100644 index 0000000..084cbe9 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/read-only-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/read-only-dependency-properties/vb/AssemblyInfo.vb b/dotnet-desktop-guide/net/wpf/properties/snippets/read-only-dependency-properties/vb/AssemblyInfo.vb new file mode 100644 index 0000000..025ee72 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/read-only-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/read-only-dependency-properties/vb/CodeSampleVb.vbproj b/dotnet-desktop-guide/net/wpf/properties/snippets/read-only-dependency-properties/vb/CodeSampleVb.vbproj new file mode 100644 index 0000000..34db9b0 --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/read-only-dependency-properties/vb/CodeSampleVb.vbproj @@ -0,0 +1,22 @@ + + + + WinExe + net6.0-windows + CodeSampleVb + true + + + + + + + + + + + + + + + diff --git a/dotnet-desktop-guide/net/wpf/properties/snippets/read-only-dependency-properties/vb/MainWindow.xaml b/dotnet-desktop-guide/net/wpf/properties/snippets/read-only-dependency-properties/vb/MainWindow.xaml new file mode 100644 index 0000000..354196f --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/read-only-dependency-properties/vb/MainWindow.xaml @@ -0,0 +1,12 @@ + + + + + + + diff --git a/dotnet-desktop-guide/net/wpf/properties/snippets/read-only-dependency-properties/vb/MainWindow.xaml.vb b/dotnet-desktop-guide/net/wpf/properties/snippets/read-only-dependency-properties/vb/MainWindow.xaml.vb new file mode 100644 index 0000000..8b029aa --- /dev/null +++ b/dotnet-desktop-guide/net/wpf/properties/snippets/read-only-dependency-properties/vb/MainWindow.xaml.vb @@ -0,0 +1,47 @@ +Namespace CodeSampleVb + + ' + ' Interaction logic for MainWindow.xaml. + ' + Partial Public Class MainWindow + Inherits Window + + ReadOnly _aquarium As New Aquarium() + + Public Sub New() + InitializeComponent() + End Sub + + Private Sub Button_Click(sender As Object, e As RoutedEventArgs) + ' Test setting a value. + _aquarium.SetValue(Aquarium.FishCountPropertyKey, _aquarium.FishCount + 1) + lblFishCount.Content = $"Aquarium fish count: {_aquarium.FishCount}" + 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. + ' Assign DependencyPropertyKey to a nonpublic field. + Friend Shared ReadOnly FishCountPropertyKey As DependencyPropertyKey = + DependencyProperty.RegisterReadOnly( + name:="FishCount", + propertyType:=GetType(Integer), + ownerType:=GetType(Aquarium), + typeMetadata:=New FrameworkPropertyMetadata()) + + ' Declare a public get accessor. + Public ReadOnly Property FishCount As Integer + Get + Return GetValue(FishCountPropertyKey.DependencyProperty) + End Get + End Property + + End Class + ' + +End Namespace diff --git a/dotnet-desktop-guide/net/wpf/toc.yml b/dotnet-desktop-guide/net/wpf/toc.yml index 055406d..b5d70db 100644 --- a/dotnet-desktop-guide/net/wpf/toc.yml +++ b/dotnet-desktop-guide/net/wpf/toc.yml @@ -94,6 +94,8 @@ items: href: properties/dependency-property-metadata.md - name: Dependency property callbacks and validation href: properties/dependency-property-callbacks-and-validation.md + - name: Read-only dependency properties + href: properties/read-only-dependency-properties.md - name: Common tasks items: - name: Implement a dependency property diff --git a/redirects_generator/definitions.json b/redirects_generator/definitions.json index a4bfe06..8f8622e 100644 --- a/redirects_generator/definitions.json +++ b/redirects_generator/definitions.json @@ -378,6 +378,11 @@ "SourceUrl": "/dotnet/desktop/wpf/advanced/dependency-property-callbacks-and-validation?view=netframeworkdesktop-4.8", "TargetUrl": "/dotnet/desktop/wpf/properties/dependency-property-callbacks-and-validation?view=netdesktop-6.0" }, + { + "Redirect": "TwoWay", + "SourceUrl": "/dotnet/desktop/wpf/advanced/read-only-dependency-properties?view=netframeworkdesktop-4.8", + "TargetUrl": "/dotnet/desktop/wpf/properties/read-only-dependency-properties?view=netdesktop-6.0" + }, // Systems - XAML {