2009-09-28 12 views
10

Ich untersuche den Silverlight-Verhaltensmechanismus, um das Model-View-ViewModel-Muster in meinen Silverlight-Anwendungen zu verwenden. Zunächst versuche ich, eine einfache Hello World zu erhalten, aber ich bin völlig in einem Fehler gefangen, für den ich keine Lösung finden kann.Fehler beim Binden einer Abhängigkeitseigenschaft an ein benutzerdefiniertes Verhalten

Was ich gerade habe ist eine Seite, die nur eine Schaltfläche enthält, die eine Nachricht anzeigen sollte, wenn Sie darauf klicken. Das click-Ereignis wird mithilfe einer von Behaviour abgeleiteten Klasse behandelt, und die Nachricht wird als eine Abhängigkeitseigenschaft des Verhaltens selbst angegeben. Das Problem tritt auf, wenn versucht wird, die Nachrichteneigenschaft an eine Eigenschaft in einer Viewmodel-Klasse zu binden, die als Datenkontext verwendet wird: Ich erhalte eine Ausnahme in dem Aufruf von InitializeComponent in der Ansicht.

Hier ist der ganze Code, den ich benutze, wie Sie sehen können, ist es ziemlich einfach. Zunächst wird die Auszeichnung von der Hauptseite und die Ansicht enthält:


MyPage

<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 (der Textblock gibt es nur zu prüfen, ob die Bindungs ​​Syntax korrekt ist)

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


Jetzt die Code, gibt es zwei Klassen: einen für das Verhalten und ein anderer für das Viewmodel:

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


Einfache genug, aber Dieser Code löst eine AG_E_PARSER_BAD_PROPERTY_VALUE [Line: 15 Position: 43] (direkt am Anfang des Werts für die Eigenschaft Nachricht festgelegt) beim Ausführen aus. Ich bin mir sicher, dass mir etwas fehlt, aber was?

Weitere Informationen: Wenn ich die Bindung aus der Message-Eigenschaft auf MyBehavior entfernen (das heißt, wenn ich den Wert auf eine statische Zeichenfolge festlegen), funktioniert es einwandfrei. Außerdem ziele ich auf silverlight 3 RTW.

Vielen Dank!


UPDATE

Es scheint, dass im Gegensatz zu WPF, Silverlight unterstützt keine Daten auf ein beliebiges Objekt Bindung von DependencyObject abgeleitet, sondern nur auf Objekte aus Framework abzuleiten. Dies ist bei Verhalten nicht der Fall, daher funktioniert die Bindung nicht.

Ich habe eine Problemumgehung gefunden here, in Form von etwas namens Ersatzbinder. Grundsätzlich geben Sie das Element und die Eigenschaft, die verknüpft werden sollen, sowie den Wert als Attribute des FrameworkElement an, das das Nicht-FrameworkElement-Objekt enthält.


UPDATE 2

Das Surrogat Bindemittel funktioniert nicht, wenn die Framework ein Interaction.Behaviors Unterelement enthält.

Ich habe eine andere Lösung here gefunden, und diese scheint zu funktionieren. Diesmal ist der verwendete Trick ein DeepSetter. Sie definieren einen dieser Setter als statische Ressource für das enthaltende StackPanel und verweisen dann die Ressource aus dem Verhalten. Also in meinem Beispiel, sollten wir die Ressourcen Abschnitt Stackpanel erweitern wie folgt:

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

... und ändern das Verhalten Erklärung Taste wie folgt:

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

UPDATE 3

Gut Nachrichten: Datenbindung für jedes DependecyObject wird auf Silverlight 4 verfügbar sein: http://timheuer.com/blog/archive/2009/11/18/whats-new-in-silverlight-4-complete-guide-new-features.aspx#dobind

+1

Ich benutze ein Verhalten mit einem benutzerdefinierten DP mit SL 4, ich habe keinen Fehler, aber die Bindung wird nicht verwendet, dh die Getter/Setter von Die Quelle wird nie aufgerufen. Hast du versucht ? – MatthieuGD

+0

Ich bin bei SilverLight3 eingesperrt, also habe ich eine Erweiterungsmethode erstellt, die es mir ermöglicht, ein Verhalten aus einem Steuerelement zu extrahieren und die gewünschte Eigenschaft darauf festzulegen. Es ist hacky, aber könnte es sonst nicht funktionieren. – jtruelove

Antwort

1

To Holen Sie sich die DataBinding-Unterstützung die Klasse sollte erben von FrameworkElement.Hoping MSFT wird in Silverlight 4

unterstützen
+0

Tatsächlich wird dies in Silverlight 4 unterstützt: http://timheuer.com/blog/archive/2009/11/18/whats-new-in-silverlight-4-complete-guide-new-features.aspx#dobind – Konamiman

Verwandte Themen