Наследование значений свойства
Наследование значений свойств — это функция системы свойств Windows Presentation Foundation (WPF). Наследование значений свойств позволяет дочерним элементам в дереве элементов получить значение определенного свойства из родительских элементов, наследуя это значение, так как оно было задано в любом месте ближайшего родительского элемента. Родительский элемент также может получить значение через наследование значений свойств, поэтому система потенциально рекурсирует весь путь к корню страницы. Наследование значений свойства не является поведением системы свойств по умолчанию; Свойство должно быть установлено с определенным параметром метаданных, чтобы это свойство вызвало наследование значений свойства на дочерних элементах.
Наследование значений свойства — наследование через вложенность
"Наследование" в качестве термина здесь не совсем то же понятие, что и наследование в контексте типов и общего объектно-ориентированного программирования, где производные классы наследуют определения членов от их базовых классов. Это значение наследования также активно в WPF: свойства, определенные в различных базовых классах, предоставляются в качестве атрибутов производных классов XAML при использовании в качестве элементов и предоставляются в качестве членов кода. Наследование значений свойств особенно касается того, как значения свойств могут наследоваться от одного элемента к другому на основе связей родительского-дочернего элемента в дереве элементов. Это дерево элементов чаще всего видно при вложении элементов внутри других элементов при определении приложений в разметке XAML. Деревья объектов также можно создавать программным способом, добавляя объекты в назначенные коллекции других объектов, а наследование значений свойств работает так же, как в готовом дереве во время выполнения.
Практические приложения наследования значений свойств
API WPF включают несколько свойств, включающих наследование свойств. Как правило, сценарий для них заключается в том, что они включают свойство, в котором необходимо задать свойство только один раз на страницу, но где это свойство также является членом одного из классов базовых элементов, поэтому также существует на большинстве дочерних элементов. Например, свойство FlowDirection определяет, какое направление потокового содержимого должно быть представлено и упорядочено на странице. Как правило, необходимо, чтобы концепция потока текста обрабатывалась последовательно во всех дочерних элементах. Если направление потока было сброшено по какой-то причине на некотором уровне дерева элементов пользователем или действием среды, оно должно быть сброшено на всём протяжении. Когда свойство FlowDirection наследуется, значение необходимо задать или сбросить только один раз на том уровне дерева элементов, который охватывает потребности презентации каждой страницы в приложении. Даже исходное значение по умолчанию наследуется таким образом. Модель наследования значений свойств по-прежнему предоставляет возможность отдельным элементам переназначать значение в редких случаях, где намеренно допускается сочетание направлений потока.
Создание настраиваемого свойства, наследуемого
Изменив метаданные пользовательского свойства, вы также можете сделать собственные настраиваемые свойства наследуемыми. Однако обратите внимание, что назначение свойства как наследуемого имеет некоторые рекомендации по производительности. В случаях, когда это свойство не имеет установленного локального значения, или значение, полученное с помощью стилей, шаблонов или привязки данных, наследуемое свойство предоставляет свои назначенные значения свойств всем дочерним элементам в логическом дереве.
Чтобы свойство участвовало в наследовании значений, создайте настраиваемое присоединенное свойство, как описано в Регистрация присоединенного свойства. Зарегистрируйте свойство с метаданными (FrameworkPropertyMetadata) и укажите параметр "Наследовать" в параметрах этих метаданных. Кроме того, убедитесь, что свойство имеет установленное значение по умолчанию, так как значение будет унаследовано. Хотя вы зарегистрировали свойство как присоединенное, вы также можете создать свойство "оболочка" для получения или задания доступа к типу владельца, так же как и для свойства зависимостей, не присоединенного. После этого можно задать наследуемое свойство с помощью прямой оболочки свойств для типа владельца или производных типов, или его можно задать с помощью синтаксиса присоединенного свойства для любого DependencyObject.
Присоединенные свойства концептуально похожи на глобальные свойства; Можно проверить значение на любом DependencyObject и получить допустимый результат. Типичный сценарий для присоединенных свойств заключается в том, чтобы задать значения свойств для дочерних элементов, и этот сценарий эффективнее, если в данном случае свойство является присоединенным свойством, которое всегда неявно присутствует в качестве присоединенного свойства для каждого элемента (DependencyObject) в дереве.
Заметка
Несмотря на то, что наследование значений свойств свойств может работать для неаттшированных свойств зависимостей, поведение наследования для неаттшированного свойства через определенные границы элементов в дереве времени выполнения не определено. Всегда используйте RegisterAttached для регистрации свойств, в которых указываете Inherits в метаданных.
Наследование свойств через границы дерева
Наследование свойств работает путем обхода дерева элементов. Это дерево часто параллельно логическому дереву. Однако всякий раз, когда вы включаете объект уровня ядра WPF в разметку, которая определяет дерево элементов, например Brush, вы создали неразрывное логическое дерево. Истинное логическое дерево концептуально не расширяется через Brush, так как логическое дерево представляет собой концепцию уровня платформы WPF. Вы можете увидеть это отражение в результатах при использовании методов LogicalTreeHelper. Однако наследование значений свойств может преодолеть этот разрыв в логическом дереве и по-прежнему передавать унаследованные значения, если наследуемое свойство зарегистрировано как присоединенное свойство и не встречается преднамеренная граница блокировки наследования (например, Frame).
См. также
.NET Desktop feedback