在自定义行为上绑定依赖属性时出错
我在探索Silverlight附加的行为机制,以便在我的Silverlight应用程序中使用Model-View-ViewModel模式。首先,我试图获得一个简单的Hello World工作,但我完全陷入了一个错误,我无法找到解决方案。在自定义行为上绑定依赖属性时出错
我现在所拥有的只是一个包含一个按钮的页面,该按钮在点击时应该显示一条消息。 click事件是通过使用派生自Behavior的类来处理的,并且该消息被指定为行为本身的依赖项属性。尝试将消息属性绑定到用作数据上下文的视图模型类上的属性时出现问题:我在视图中调用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>
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>
现在代码中,有两类:一个是行为,另一个用于视图模型:
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属性设置的值的开始处)异常。我确定我错过了什么,但是什么?
附加信息:如果我从MyBehavior上的Message属性(也就是说,如果将它的值设置为任何静态字符串)中移除该绑定,它将正常工作。此外,我瞄准silverlight 3 RTW。
非常感谢!
UPDATE
似乎不像WPF,Silverlight不支持数据自DependencyObject派生的任何对象绑定,但仅限于自FrameworkElement派生的对象。这不是行为的情况,因此绑定不起作用。
我找到了一种解决方法here,其形式为名为代理活页夹的东西。基本上你可以将要绑定的元素和属性以及值指定为包含非FrameworkElement对象的FrameworkElement的属性。
UPDATE 2
当FrameworkElement的含有Interaction.Behaviors子元件的替代粘合剂不起作用。
我发现了另一个解决方案here,这似乎工作。这一次,使用的技巧是一个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
To获取数据绑定支持类应该从FrameworkElement.Hoping MSFT继承会给予支持Silverlight 4中
事实上,这在Silverlight 4中得到了支持:http://timheuer.com/blog/archive/2009/11/18/whats-new-in-silverlight-4-complete-guide-new-features.aspx#dobind – Konamiman 2009-11-19 16:17:53
我使用行为与自定义DP与SL 4,我没有错误,但结合不使用的IE的getter/setter源永远不会被调用。你试过了吗 ? – MatthieuGD 2010-04-28 21:58:00
我被锁定到SilverLight3,所以我做了一个扩展方法,允许我从控件中提取行为并在其上设置所需的属性。这是hacky,但无法让它工作,否则。 – jtruelove 2013-04-23 18:29:41