Fehler beim Binden einer Abhängigkeitseigenschaft an ein benutzerdefiniertes Verhalten

Ich untersuche den an Silverlight angehängten Verhaltensmechanismus, um das Model-View-ViewModel-Muster in meinen Silverlight-Anwendungen zu verwenden. Zunächst versuche ich, eine einfache Hello World zum Laufen zu bringen, stecke aber völlig in einem Fehler, für den ich keine Lösung finden kann.

Was ich gerade habe, ist eine Seite, die nur eine Schaltfläche enthält, die beim Klicken eine Meldung anzeigen soll. Das Klickereignis wird mithilfe einer von Behaviour abgeleiteten Klasse verarbeitet, und die Nachricht wird als Abhängigkeitseigenschaft des Verhaltens selbst angegeben. Das Problem tritt auf, wenn versucht wird, die Nachrichteneigenschaft an eine Eigenschaft einer Viewmodel-Klasse zu binden, die als Datenkontext verwendet wird: Ich erhalte eine Ausnahme beim Aufruf vonInitializeComponent in der Ansicht.

Hier ist der Code, den ich verwende, wie Sie sehen, ist er ziemlich einfach. Zuerst das Markup der Hauptseite und die darin enthaltene Ansicht:


Meine Seite

<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>


Meine Sicht (Der TextBlock dient nur zur Überprüfung der korrekten Bindungssyntax.)

<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>


Im Code gibt es zwei Klassen: eine für das Verhalten und eine für das Ansichtsmodell:

MyViewmodel

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


Mein Benehmen

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);
    }
}


Einfach genug, aber dieser Code wirft eineAG_E_PARSER_BAD_PROPERTY_VALUE [Line: 15 Position: 43] (direkt zu Beginn des Werts, der für die Message-Eigenschaft festgelegt wird) Ausnahme beim Ausführen. Ich bin sicher, dass mir etwas fehlt, aber was?

Zusätzliche Informationen: Wenn ich die Bindung von der Message-Eigenschaft in MyBehavior entferne (d. H. Wenn ich den Wert auf eine statische Zeichenfolge setze), funktioniert dies einwandfrei. Außerdem ziele ich auf Silverlight 3 RTW.

Danke vielmals!


AKTUALISIEREN

Es scheint, dass Silverlight im Gegensatz zu WPF keine Datenbindung für Objekte unterstützt, die von DependencyObject abgeleitet sind, sondern nur für Objekte, die von FrameworkElement abgeleitet sind. Dies ist bei Behaviour nicht der Fall, daher funktioniert die Bindung nicht.

Ich habe eine Problemumgehung gefundenHierin Form von etwas namens Surrogat-Bindemitteln. Grundsätzlich geben Sie das zu bindende Element und die zu bindende Eigenschaft sowie den Wert als Attribute des FrameworkElement an, das das Nicht-FrameworkElement-Objekt enthält.


UPDATE 2

Der Ersatzordner funktioniert nicht, wenn das FrameworkElement ein Interaction.Behaviors-Unterelement enthält.

Ich habe eine andere Lösung gefundenHierund dieser scheint zu funktionieren. Diesmal ist der verwendete Trick aDeepSetter. Sie definieren einen dieser Setter als statische Ressource im enthaltenden StackPanel und verweisen dann aus dem Verhalten auf die Ressource. In meinem Beispiel sollten wir den Abschnitt StackPanel-Ressourcen folgendermaßen erweitern:

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

... und ändern Sie die Verhaltenserklärung der Schaltfläche wie folgt:

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

UPDATE 3

Gute Nachricht: Die Datenbindung für jedes DependecyObject ist in Silverlight 4 verfügbar:http://timheuer.com/blog/archive/2009/11/18/whats-new-in-silverlight-4-complete-guide-new-features.aspx#dobind

Antworten auf die Frage(1)

Ihre Antwort auf die Frage