在自定义行为上绑定依赖项属性时出错

Kon*_*man 10 silverlight silverlight-3.0

我正在探索Silverlight附加的行为机制,以便在我的Silverlight应用程序中使用Model-View-ViewModel模式.首先,我试图让一个简单的Hello World工作,但我完全陷入了一个我无法找到解决方案的错误.

我现在拥有的是一个只包含一个按钮的页面,该按钮在单击时应显示一条消息.通过使用从Behavior派生的类来处理click事件,并将消息指定为行为本身的依赖项属性.当尝试将message属性绑定到用作数据上下文的viewmodel类的属性时出现问题:我InitializeComponent在视图中的调用中获得了一个exeption .

这是我正在使用的所有代码,因为您可以看到它非常简单.首先是主页面的标记及其包含的视图:


我的页面

<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>
Run Code Online (Sandbox Code Playgroud)


MyView(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>
Run Code Online (Sandbox Code Playgroud)


现在代码中有两个类:一个用于行为,另一个用于viewmodel:

MyViewmodel

public class MyViewmodel
{
    public string MyMessage
    {
        get { return "Hello, world!"; }
    }
}
Run Code Online (Sandbox Code Playgroud)


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);
    }
}
Run Code Online (Sandbox Code Playgroud)


很简单,但是这段代码在运行时会抛出一个AG_E_PARSER_BAD_PROPERTY_VALUE [Line: 15 Position: 43](在为Message属性设置的值的开头).我确定我错过了什么,但是什么?

附加信息:如果我从MyBehavior上的Message属性中删除绑定(即,如果我将其值设置为任何静态字符串),它可以正常工作.另外,我的目标是silverlight 3 RTW.

非常感谢!


UPDATE

似乎与WPF不同,Silverlight不支持对源自DependencyObject的任何对象进行数据绑定,而只支持从派生自FrameworkElement的对象进行数据绑定.这不是行为的情况,因此绑定不起作用.

我在这里找到了一种解决方法,以一种名为代理绑定器的形式.基本上,您将要绑定的元素和属性以及值指定为包含非FrameworkElement对象的FrameworkElement的属性.


更新2

当FrameworkElement包含Interaction.Behaviors子元素时,代理绑定器不起作用.

在这里找到了另一个解决方案,这个似乎有效.这一次,使用的技巧是DeepSetter.您可以在包含StackPanel的定义中将其中一个setter定义为静态资源,然后从该行为中引用该资源.所以在我的例子中,我们应该扩展StackPanel资源部分,如下所示:

<StackPanel.Resources>
    <local:MyViewmodel x:Key="MyResource"/>
    <local:DeepSetter 
        x:Key="MyBehaviorSetter"
        TargetProperty="Message"
        BindingExport="{Binding MyMessage, Source={StaticResource MyResource}}"/>
</StackPanel.Resources>
Run Code Online (Sandbox Code Playgroud)

...并修改按钮的行为声明,如下所示:

<local:MyBehavior local:DeepSetter.BindingImport="{StaticResource MyBehaviorSetter}"/>
Run Code Online (Sandbox Code Playgroud)

更新3

好消息:任何DependecyObject的数据绑定都将在Silverlight 4上提供:http://timheuer.com/blog/archive/2009/11/18/whats-new-in-silverlight-4-complete-guide-new-features 的.aspx#dobind

Joy*_*uru 1

要获得 DataBinding 支持,该类应从 FrameworkElement 继承。希望 MSFT 将在 Silverlight 4 中提供支持