Blend Behaviors - можете ли вы связать их свойства? - PullRequest
7 голосов
/ 08 июня 2011

В настоящее время я перенес несколько созданных мною поведений в Blend Behaviors, чтобы они поддерживали перетаскивание в Expression Blend. Я заметил, что авторы поведения Blend склонны определять свойства поведения как свойства зависимости.

Я создал поведение, TiltBehaviour, которое предоставляет открытое свойство зависимости TiltFactor типа double. В Expression Blend я могу установить значение этого свойства, однако опция добавления «Привязки данных ...» недоступна:

cannot bind to behaviour property

Я также заметил, что Поведения распространяются на DependencyObject, поэтому они не имеют DataContext и поэтому не могут наследовать DataContext элемента, к которому они привязаны. Это похоже на настоящую слабость для меня!

Итак, суть в том, что если я не могу установить привязку к своему свойству зависимостей поведения в Blend, и оно не наследует DataContext, зачем вообще использовать свойства зависимости? Я мог бы просто использовать свойства CLR.

Ответы [ 2 ]

8 голосов
/ 14 июня 2011

Режимы смешивания были бы почти бесполезны, если бы они не поддерживали связывание! Я воссоздаю ваше поведение наклона, и оно поддерживает связывание в Blend 4 без проблем, поэтому я не знаю точно, где вы ошиблись. Возможно, вы сможете воспроизвести мой простой пример, а затем сделать вывод, что не так с вашей настройкой.

Вот (нефункциональное) поведение наклона со свойством зависимости:

public class TiltBehavior : Behavior<FrameworkElement>
{
    public double TiltFactor
    {
        get { return (double)GetValue(TiltFactorProperty); }
        set { SetValue(TiltFactorProperty, value); }
    }

    public static readonly DependencyProperty TiltFactorProperty =
        DependencyProperty.Register("TiltFactor", typeof(double), typeof(TiltBehavior), new UIPropertyMetadata(0.0));
}

Затем просто создайте новое окно и поместите поведение в сетку, и Blend создаст это:

<Grid>
    <i:Interaction.Behaviors>
        <local:TiltBehavior/>
    </i:Interaction.Behaviors>
</Grid>

и параметр «Связывание данных ...» доступен на вкладке свойств.

Я проверил это в проектах WPF и Silverlight. Все встроенные поведения, триггеры и действия поддерживают привязку благодаря использованию свойств зависимости, а все образцы Blend интенсивно используют привязку, поэтому имеет для работы.

На самом деле вы можете просто вставить встроенное поведение типа FluidMoveBehavior в свою сетку и проверить, что Duration, который является свойством зависимости, поддерживает связывание. Если это не сработает, у меня нет представления о том, что происходит!


Давайте теперь рассмотрим, как работает привязка для этих странных зверей, называемых поведением.

Как программисты WPF или Silverlight, мы хорошо знакомы с привязкой для таких вещей, как FrameworkElement. У него есть свойство с именем DataContext, которым мы можем манипулировать для управления источником привязки по умолчанию, и это свойство наследуется вложенными элементами, когда мы не переопределяем его.

Но поведение (и триггеры, и действия) не типа FrameworkElement. В конечном итоге они получены из DependencyObject, как и следовало ожидать. Но хотя мы можем использовать привязку для любого класса, полученного из DependencyObject, наш знакомый DataContext отсутствует на этом низком уровне, и поэтому привязка должна предоставить источник. Это не очень удобно.

Таким образом, поведение получается (в любом случае в WPF) из Animatable, а Animatable происходит из Freezable. Класс Freezable - это то, где простота объектов зависимостей пересекается со сложностью элементов каркаса. Класс Freezable также является базовым классом для более привычных вещей, таких как кисти и источники изображений. Этим классам не нужна полная сложность элемента инфраструктуры, но они хотят участвовать ограниченным образом с элементами, с которыми они связаны.

В результате сложного магического процесса экземпляры Freezable получают контекст наследования: элемент каркаса, с которым они наиболее тесно связаны, а при использовании привязки по умолчанию (без привязки к источнику) Freezable использует DataContext вместо этого ассоциированного элемента.

На самом деле, когда вы узнаете о поведении, AssociatedObject является центральной концепцией; для поведения это вещь, к которой привязано поведение. Но важным моментом является то, что все Freezable объекты могут использовать DataContext своих AssociatedObject по доверенности.

Вся эта магия - это то, что Джош Смит называет:

И все это приводит к тому, что из-за Hillberg Freezable Trick поведения Blend поддерживают привязку с использованием контекста данных их связанного элемента в качестве источника по умолчанию. В результате привязки к поведению, похоже, «просто работают» без каких-либо усилий с нашей стороны. Благодаря этому поведение в тысячу раз полезнее.

4 голосов
/ 08 июня 2011

Редактировать: Дейн - это правильно, вы все равно можете привязать к DataContext, который создан искусственно, как часто вы видели, как люди связываются с SolidColorBrush.Color? Это также работает, хотя SolidColorBrush наследуется от DependencyObject и, следовательно, не имеет DataContext.

См. это сообщение в блоге о контексте наследования .

Дело в том, что поскольку поведения привязаны, они не появляются в логическом дереве и, следовательно, не наследуют DataContext в любом случае.

...