我在探索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
我使用行爲與自定義DP與SL 4,我沒有錯誤,但結合不使用的IE的getter/setter源永遠不會被調用。你試過了嗎 ? – MatthieuGD 2010-04-28 21:58:00
我被鎖定到SilverLight3,所以我做了一個擴展方法,允許我從控件中提取行爲並在其上設置所需的屬性。這是hacky,但無法讓它工作,否則。 – jtruelove 2013-04-23 18:29:41