Ошибка при привязке свойства зависимости к пользовательскому поведению

Я изучаю механизм прикрепленного поведения Silverlight, чтобы использовать шаблон Model-View-ViewModel в моих приложениях Silverlight. Начнем с того, что я пытаюсь заставить работать простой Hello World, но я полностью застрял в ошибке, для которой я не могу найти решение.

Сейчас у меня есть страница, которая содержит кнопку, которая должна отображать сообщение при нажатии. Событие click обрабатывается с использованием класса, производного от Behavior, и сообщение указывается как свойство зависимости самого поведения. Проблема возникает при попытке связать свойство сообщения со свойством класса viewmodel, используемого в качестве контекста данных: я получаю исключение при вызовеInitializeComponent в представлении.

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


Моя страница

<UserControl x:Class="MyExample.MyPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:MyExample"
    >
    <Grid x:Name="LayoutRoot">
        <local:MyView/>
    </Grid>
</UserControl>


Мой вид (TextBlock существует только для проверки правильности синтаксиса привязки)

<UserControl x:Class="MyExample.MyView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
    xmlns:local="clr-namespace:MyExample"
    Width="400" Height="300">
    <StackPanel Orientation="Vertical" x:Name="LayoutRoot" Background="White">
        <StackPanel.Resources>
            <local:MyViewmodel x:Key="MyResource"/>
        </StackPanel.Resources>
        <TextBlock Text="This button will display the following message:"/>
        <TextBlock Text="{Binding MyMessage, Source={StaticResource MyResource}}" FontStyle="Italic"/>
        <Button x:Name="MyButton" Content="Click me!">
            <i:Interaction.Behaviors>
                <local:MyBehavior Message="{Binding MyMessage, Source={StaticResource MyResource}}"/>
            </i:Interaction.Behaviors>
        </Button>
    </StackPanel>
</UserControl>


Теперь в коде есть два класса: один для поведения и другой для модели представления:

MyViewmodel

public class MyViewmodel
{
    public string MyMessage
    {
        get { return "Hello, world!"; }
    }
}


MyBehavior

public class MyBehavior : Behavior<Button>
{
    public static readonly DependencyProperty MessageProperty =
        DependencyProperty.Register("Message",
        typeof(string), typeof(MyBehavior),
        new PropertyMetadata("(no message)"));

    public string Message
    {
        get { return (string)GetValue(MessageProperty); }
        set { SetValue(MessageProperty, value); }
    }

    protected override void OnAttached()
    {
        base.OnAttached();
        AssociatedObject.Click += new RoutedEventHandler(AssociatedObject_Click);
    }

    protected override void OnDetaching()
    {
        base.OnDetaching();
        AssociatedObject.Click -= new RoutedEventHandler(AssociatedObject_Click);
    }

    void AssociatedObject_Click(object sender, RoutedEventArgs e)
    {
        MessageBox.Show(Message);
    }
}


Достаточно просто, но этот кодAG_E_PARSER_BAD_PROPERTY_VALUE [Line: 15 Position: 43] (прямо в начале значения, устанавливаемого для свойства Message) исключение при запуске. Я уверен, что что-то упустил, но что?

Дополнительная информация: если я удаляю привязку из свойства Message в MyBehavior (то есть, если я устанавливаю его значение для любой статической строки), она работает нормально. Также я ориентируюсь на Silverlight 3 RTW.

Большое спасибо!


ОБНОВИТЬ

Кажется, что в отличие от WPF Silverlight не поддерживает привязку данных ни к одному объекту, производному от DependencyObject, а только к объектам, производным от FrameworkElement. Это не относится к поведению, следовательно, привязка не работает.

Я нашел обходной путьВотв форме чего-то, названного суррогатными связующими. По сути, вы указываете элемент и свойство, которые должны быть связаны, а также значение в качестве атрибутов FrameworkElement, содержащих объект не-FrameworkElement.


ОБНОВЛЕНИЕ 2

Суррогатное связующее не работает, когда FrameworkElement содержит вложенный элемент Interaction.Behaviors.

Я нашел другое решениеВоти этот, кажется, работает. На этот раз использовался трюкDeepSetter, Вы определяете один из таких сеттеров как статический ресурс на содержащей StackPanel, а затем ссылаетесь на ресурс из поведения. Так что в моем примере мы должны расширить раздел ресурсов StackPanel следующим образом:

<StackPanel.Resources>
    <local:MyViewmodel x:Key="MyResource"/>
    <local:DeepSetter 
        x:Key="MyBehaviorSetter"
        TargetProperty="Message"
        BindingExport="{Binding MyMessage, Source={StaticResource MyResource}}"/>
</StackPanel.Resources>

... и измените объявление поведения кнопки следующим образом:

<local:MyBehavior local:DeepSetter.BindingImport="{StaticResource MyBehaviorSetter}"/>

ОБНОВЛЕНИЕ 3

Хорошая новость: привязка данных для любого DependecyObject будет доступна в Silverlight 4:http://timheuer.com/blog/archive/2009/11/18/whats-new-in-silverlight-4-complete-guide-new-features.aspx#dobind

Ответы на вопрос(1)

Ваш ответ на вопрос