2010-07-16 13 views
10

Ich habe ein UserControl, das ich an Datenbindung teilnehmen möchte. Ich habe die Abhängigkeitseigenschaften im Benutzersteuerelement eingerichtet, kann aber nicht funktionieren.Datenbindung an ein Benutzersteuerelement in WPF

Der uc zeigt den richtigen Text, wenn ich es mit statischem Text aufrufen (z. B. BlueText = "ABC"). Wenn ich versuche, es an eine lokale öffentliche Eigenschaft zu binden, ist es immer leer.

<src:BlueTextBox BlueText="Feeling blue" />   <!--OK--> 
<src:BlueTextBox BlueText="{Binding Path=MyString}" /> <!--UserControl always BLANK!--> 
<TextBox Text="{Binding Path=MyString}" Width="100"/> <!--Simple TextBox Binds OK--> 

Ich habe den Code auf das folgende vereinfachte Beispiel gekocht. Hier ist die XAML des Usercontrol:

<UserControl x:Class="Binding2.BlueTextBox" ... 
    <Grid> 
     <TextBox x:Name="myTextBox" Text="{Binding BlueText}" Foreground="Blue" Width="100" Height="26" /> 
    </Grid> 

Hier ist der Code, hinter der Usercontrol:

public partial class BlueTextBox : UserControl 
{ 
    public BlueTextBox() 
    { 
     InitializeComponent(); 
     DataContext = this; // shouldn't do this - see solution 
    } 

    public static readonly DependencyProperty BlueTextProperty = 
     DependencyProperty.Register("BlueText", typeof(string), typeof(BlueTextBox)); 

    public string BlueText 
    { 
     get { return GetValue(BlueTextProperty).ToString(); } 
     set { SetValue(BlueTextProperty, value.ToString()); } 
    } 

Dies scheint, wie es wirklich einfach sein sollte, aber ich kann nicht damit es funktioniert. Danke für Ihre Hilfe!

Weitere Informationen: Als ich die von Eugene vorgeschlagene Lösung versuchte, bemerkte ich ein eigenartiges Verhalten. Ich habe den Metadaten ein PropertyChangedCallback hinzugefügt. Dadurch kann ich beobachten, wie BlueText eingestellt wird. Wenn die Zeichenfolge auf einen statischen Wert gesetzt wird (= "feeling blue"), wird das PropertyChanged-Ereignis ausgelöst. Der Datenbindungsfall löst PropertyChanged nicht aus. Ich denke, das bedeutet, dass der datengebundene Wert nicht an das Benutzersteuerelement gesendet wird. (Ich glaube, dass der Konstruktor im statischen Fall nicht aufgerufen wird)

Lösung: Die Probleme wurden von Arcturus und jpsstavares korrekt identifiziert. Zuerst überschrieb ich die Datenbindung, wenn DataContext = dies im Konstruktor des Steuerelements festgelegt ist. Dies verhinderte, dass der datengebundene Wert gesetzt wurde. Außerdem musste ich das Steuerelement x: Name = root benennen und den Binding ElementName = root in XAML angeben. Um die TwoWay-Bindung zu erhalten, musste ich Mode = TwoWay im Caller einstellen. Hier ist der richtige Code:

<src:BlueTextBox BlueText="{Binding Path=MyString, Mode=TwoWay}}" /> <!--OK--> 

Nun ist die XAML in dem Usercontrol:

<UserControl x:Class="Binding2.BlueTextBox" x:Name="root"... 
    <Grid> 
     <TextBox x:Name="myTextBox" Text="{Binding ElementName=root, Path=BlueText}" Foreground="Blue" Width="100" Height="26" /> 
    </Grid> 

Schließlich entfernte ich die Datacontext = diese im Konstruktor des Usercontrol.

public BlueTextBox() 
    { 
     InitializeComponent(); 
     //DataContext = this; -- don't do this 
    } 

Vielen Dank für die enorme Hilfe!

Antwort

11

Sie legen die Datacontext in der Steuerung an sich selbst, so dass die Datacontext überschrieben wird, wenn sie in andere Steuerelemente diese Steuerung verwenden. Unter Ihrer Bindung als Beispiel in Ihrer Situation:

<src:BlueTextBox BlueText="{Binding Path=MyString}" /> 

Einmal geladen und alle Datacontext gesetzt ist, wird es aussehen für den Weg MyString in Ihrer BlueTextBox Sache Kontrolle wegen Sie den Datacontext es einstellen. Ich nehme an, das ist nicht so, wie Sie das haben wollten;).

Lösung:

Ändern Sie den Text entweder einer der zwei Bindungen Bindung:

{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type src:BlueTextBox}}, Path=BlueText} 

oder

Namen Ihrer Kontrolle Root (oder so ähnlich)

<UserControl x:Name="Root" 

{Binding ElementName=Root, Path=BlueText} 

Und entfernen Sie die

DataContext = this; 

aus dem Konstruktor Ihrer Usercontrol und es soll wie ein Zauber arbeiten ..

0

Möglicherweise müssen Sie Ihrer Eigenschaft FrameworkPropertyMetadata hinzufügen, wo FrameworkPropertyMetadataOptions.AffectsRender und AffectsMeasure angegeben werden.

FrameworkPropertyMetadataOptions enumeration MSDN article

+0

Versuchte Einstellung sowohl AffectsRender und AffectsMeasure während der Registrierung, aber dies hatte keine Wirkung. Vielen Dank. – RaoulRubin

2

denke ich, in diesem Fall, dass Sie die ElementName Eigenschaft in der Bindung einstellen müssen. Etwas wie folgt aus:

<UserControl x:Class="Binding2.BlueTextBox" x:Name="blueTextBox"... 
<Grid> 
    <TextBox x:Name="myTextBox" Text="{Binding ElementName=blueTextBox, Path=BlueText}" Foreground="Blue" Width="100" Height="26" /> 
</Grid> 
0

Ich weiß, dies ist ein altes Thema, aber immer noch.

erwähnen auch die PropertyChangedCallback auf der UIPropertyMetadata Ihre DP