Подтвердить что ты не робот

Как точно встраиваемые свойства работают в WPF?

Я немного озадачен тем, как Attached Properties передают свои ценности как родительским, так и дочерним элементам. TextElement.FontFamily приводит к тому, что дочерние элементы наследуют значение, присвоенное этому свойству (по-видимому, нисходящая операция, от родителя к дочерней). Grid.Column приводит к тому, что родительский элемент отображает этого дочернего элемента в определенной позиции (по-видимому, восходящая операция, от дочернего к родительскому). Как значить значения Attached Property, чтобы либо течь вверх, либо вниз? Является ли моя концепция этого неправильной, или есть ли недостающая часть, которая вложит все это в перспективу?

<StackPanel TextElement.FontFamily="Wingdings">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>

        <Button Grid.Column="1" Content="My Button"/>
    </Grid>
</StackPanel>
4b9b3361

Ответ 1

Здесь есть два понятия: свойства зависимостей и привязанные свойства зависимостей. "Attached Properties" - это свойства зависимостей, и в качестве такой зависимости зависимостей наследование свойств.

В отношении основных свойств зависимостей очень грубым утверждением было бы то, что они в основном наследуют свои значения от родительских элементов дерева wpf (логического/визуального). Свойство зависимости (прилагается или нет) наследует его значение "вниз", если его metadata задается с помощью FrameworkPropertyMetadataOptions. Наследовать флаг, и во многих случаях это так.

Прикрепленные свойства - это свойства, которые могут быть установлены на любом объекте wpf (в основном, по крайней мере, на DependencyObject) с помощью метода DependencyObject.SetValue. Целью этого механизма является "прикрепить" к другим объектам информацию, необходимую родительским объектам, а не к самим дочерним объектам. Например, Grid.Row является прикрепленным свойством, требуемым сеткой для размещения элементов в пределах области рендеринга.

Свойства зависимостей наследуются "вниз" автоматически с помощью объектной системы wpf.

Прикрепленные свойства проверяются "вверх" явно, в коде конкретных объектов. В случае Grid, после определения места размещения своих элементов, он проверяет значение свойств Grid.Row и Grid.Column для каждого содержащегося элемента.

Также часто используется способ создания настраиваемых свойств, которые каким-либо образом модифицируют объекты, к которым они привязаны (например, Drag'n'Drop функциональность через прикрепленные свойства).

В качестве дополнительной заметки хорошим примером наследующего прикрепленного свойства является TextElement.FontFamily. Свойства Grid.Row и Grid.Column не имеют установленный флаг Inherits.

TextElement.FontFamily, из Reflector:

 FontFamilyProperty = DependencyProperty.RegisterAttached("FontFamily", typeof(FontFamily), typeof(TextElement), new FrameworkPropertyMetadata(SystemFonts.MessageFontFamily, FrameworkPropertyMetadataOptions.Inherits | FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.AffectsMeasure), new ValidateValueCallback(TextElement.IsValidFontFamily));

Grid.Row, из Reflector:

 RowProperty = DependencyProperty.RegisterAttached("Row", typeof(int), typeof(Grid), new FrameworkPropertyMetadata(0, new PropertyChangedCallback(Grid.OnCellAttachedPropertyChanged)), new ValidateValueCallback(Grid.IsIntValueNotNegative));

Ответ 2

От MSDN:

Хотя прикрепленные свойства настраиваются на любом объекте, это автоматически не означает, что установка свойства приведет к ощутимому результату или что значение когда-либо будет использоваться другим объектом. Как правило, прикрепленные свойства предназначены для того, чтобы объекты, поступающие из самых разных возможных иерархий классов или логических отношений, могли сообщать общую информацию о типе, который определяет прикрепленное свойство. Тип, который определяет прикрепленное свойство, обычно следует за одной из этих моделей:

  • Тип, определяющий прикрепленный свойство сконструировано таким образом, чтобы оно быть родительским элементом элементов который установит значения для прилагаемого имущество. Затем тип выполняет итерацию дочерние объекты через внутреннюю логику против некоторой структуры дерева объектов, получает значения и действует на эти значения в некотором роде.

  • Тип, определяющий прикрепленный собственность будет использоваться в качестве ребенка элемент для множества возможных родительские элементы и модели содержимого.

  • Тип, определяющий прикрепленный свойство представляет собой сервис. Другие типы заданные значения для прилагаемых имущество. Тогда, когда элемент, который set свойство оценивается в контекст сервиса, прилагаемый значения свойств получены через внутренняя логика класса обслуживания.

Пример родительского прикрепленного свойства

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

DockPanel определяет прикрепленное свойство DockPanel.Dock, а DockPanel имеет код уровня класса как часть его логики обработки (в частности, MeasureOverride и ArrangeOverride). Экземпляр DockPanel всегда проверяет, установил ли какой-либо из его непосредственных дочерних элементов значение DockPanel.Dock. Если это так, эти значения становятся входными для логики визуализации, применяемой к этому конкретному дочернему элементу. Вложенные экземпляры DockPanel обрабатывают свои собственные коллекции дочерних элементов, но это поведение специфично для реализации процесса DockPanel для процессов DockPanel.Dock. Теоретически возможно иметь прикрепленные свойства, которые влияют на элементы за пределами непосредственного родителя. Если прикрепленное свойство DockPanel.Dock установлено на элементе, для которого не действует родительский элемент DockPanel, никаких ошибок и исключений не возникает. Это просто означает, что было задано глобальное значение свойства, но у него нет текущего родителя DockPanel, который мог бы использовать информацию.

Ответ 3

Простыми словами это то, как я это понимаю (пожалуйста, поправьте меня, если я ошибаюсь).

Объект (A) реализует свойство, которое будет прикрепляться к другому объекту (B) (объект B даже не знает о существовании этого "прикрепляемого" свойства). Объект B должен наследовать от DependencyObject.

Объект A также реализует статический метод для проверки его "прикрепляемого" свойства в других объектах A.GetAttachedProperty(B).

Если B имеет прикрепленное свойство от A, A.GetAttachedProperty будет читать и возвращать его значение. В противном случае A попытается прочитать его и вернуть null, так как он не существует.