Свойства зависимости «только для чтения» (WPF .NET)

С помощью свойств зависимостей «только для чтения» можно предотвратить задание значений свойств за пределами кода. В этой статье обсуждаются существующие свойства зависимостей «только для чтения», а также сценарии и методы создания пользовательского свойства зависимостей «только для чтения».

Важно!

Документация по рабочему столу для .NET 7 и .NET 6 находится в стадии разработки.

Необходимые компоненты

Для понимания статьи нужно иметь базовые знания о свойствах зависимостей и прочитать Общие сведения о свойствах зависимостей. Чтобы понимать примеры в этой статье полезно познакомиться с языком XAML и узнать, как создавать приложения WPF.

Существующие свойства зависимостей «только для чтения»

Свойства зависимостей только для чтения обычно имеют состояние отчета, и их нельзя изменять с помощью метода доступа public. Например, платформа Windows Presentation Foundation (WPF) реализует свойство IsMouseOver как доступное только для чтения, так как его значение должно определяться только входными данными мыши. Если свойству IsMouseOver разрешены другие входные данные, его значение может стать несогласованным с входными данными мыши. Однако многие существующие свойства зависимостей, доступные только для чтения, не задаются с помощью метода доступа public, но имеют значения, определяемые несколькими входными данными.

Использование свойств зависимостей «только для чтения»

Свойства зависимостей «только для чтения» не применяются в нескольких сценариях, где свойства зависимостей обычно предлагают решение. Неприменимые сценарии включают привязку данных, применение стиля к значению, проверке, анимации и наследованию. Однако свойство зависимости, доступное только для чтения, можно использовать в стиле в качестве триггера свойства. Например, IsMouseOver обычно используется для активации изменений фона, переднего плана или другого видимого свойства элемента управления при наведении на него указателя мыши. Система свойств WPF обнаруживает и сообщает об изменениях свойств зависимостей «только для чтения», тем самым поддерживая функциональные возможности триггера свойств. Свойства зависимостей «только для чтения» также полезны при реализации свойства зависимостей типа коллекции, где только элементы коллекции должны быть записываемыми, а не сам объект коллекции. Дополнительные сведения см. в статье Свойства зависимостей типа коллекции.

Примечание.

Только свойства зависимостей, а не обычные свойства среды CLR, можно использовать в качестве триггеров свойств в стиле.

Создание пользовательских свойств зависимостей «только для чтения»

Перед созданием свойства зависимостей, предназначенного только для чтения, проверьте неприменимые сценарии.

Процесс создания свойства зависимостей «только для чтения» во многом аналогичен созданию свойств зависимостей для чтения и записи со следующими различиями:

  • При регистрации свойства «только для чтения» вызовите RegisterReadOnly вместо Register.

  • При реализации оболочки свойства среды CLR убедитесь, что у нее нет общедоступного метода доступа set.

  • RegisterReadOnly возвращает DependencyPropertyKey вместо DependencyProperty. Сохраните DependencyPropertyKey в закрытом члене класса.

Значение свойства зависимостей «только для чтения» можно определить с помощью любой выбранной логики. Рекомендуемый способ задать значение свойства, изначально или как часть логики среды выполнения, — использовать перегрузку SetValue, которая принимает параметр типа DependencyPropertyKey. Предпочтительнее использовать SetValue, чтобы обойти систему свойств и задать резервное поле напрямую.

Как и где значение свойства зависимостей «только для чтения» в приложении влияет на уровень доступа, назначаемый члену класса, который хранит DependencyPropertyKey. Если значение свойства задается только в пределах класса, который регистрирует свойство зависимостей, можно использовать модификатор доступа private. Для сценариев, в которых значения свойств зависимостей влияют друг на друга, можно использовать парные PropertyChangedCallback и обратные CoerceValueCallback вызовы для активации изменений значений. Дополнительные сведения см. в статье Метаданные свойств зависимостей.

Если необходимо изменить значение свойства зависимостей только для чтения извне класса, который его регистрирует, можно использовать модификатор доступа internal для DependencyPropertyKey. Например, можно вызвать SetValue из обработчика событий в той же сборке. В следующем примере определяется класс Aquarium, который вызывает RegisterReadOnly для создания свойства зависимостей, доступного только для чтения FishCount. DependencyPropertyKey назначается полю internal static readonly, чтобы код в той же сборке мог изменить значение свойства зависимостей, доступное только для чтения.

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);
}
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

Поскольку система свойств WPF не распространяет DependencyPropertyKey на пределы кода код, у свойств зависимостей «только для чтения» безопасность записи лучше, чем у свойств зависимостей для чтения и записи. Используйте свойство зависимостей «только для чтения», если необходимо ограничить доступ на запись теми, у кого есть ссылка на DependencyPropertyKey.

Напротив, идентификатор свойств зависимостей для чтения и записи доступен через систему свойств независимо от того, какой модификатор доступа назначен. Дополнительные сведения см. в статье Безопасность свойств зависимостей.

См. также