2010-07-16 21 views
10

Ho un UserControl a cui voglio partecipare in associazione dati. Ho impostato le proprietà di dipendenza nel controllo utente, ma non riesco a farlo funzionare.Associazione dati a un UserControl in WPF

L'uc visualizza il testo corretto quando lo chiamo con testo statico (ad esempio BlueText = "ABC"). Quando provo a collegarlo a una proprietà pubblica locale, è sempre vuoto.

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

Ho ridotto il codice al seguente esempio semplificato. Ecco il codice XAML di UserControl:

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

Qui è il codice dietro di 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()); } 
    } 

Questo sembra che dovessero essere veramente facili, ma non riesco a farlo funzionare. Grazie per l'aiuto!

Altre informazioni: Quando ho provato la correzione suggerita da Eugene, ho notato un comportamento particolare. Ho aggiunto un PropertyChangedCallback ai metadati; questo mi consente di osservare il valore di BlueText che si sta impostando. Quando si imposta la stringa su un valore statico (= "feeling blue"), viene generato l'evento PropertyChanged. Il caso di associazione dei dati non attiva PropertyChanged. Penso che questo significhi che il valore legato ai dati non viene inviato a UserControl. (Penso che il costruttore non venga chiamato nel caso statico)

Soluzione: I problemi sono stati correttamente identificati da Arcturus e jpsstavares. Innanzitutto, stavo sovrascrivendo il binding dei dati quando è impostato DataContext = this nel costruttore del controllo. Questo ha impedito il set-up del valore associato ai dati. Dovevo anche nominare il controllo x: Name = root, e specificare Binding ElementName = root int lo XAML. Per ottenere il binding TwoWay, avevo bisogno di impostare Mode = TwoWay nel chiamante. Ecco il codice corretto:

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

Ora il XAML nella 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> 

Finalmente ho tolto il DataContext = questo nel costruttore di UserControl.

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

Grazie a tutti per l'enorme aiuto!

risposta

11

Si imposta il DataContext nel controllo a se stesso, sovrascrivendo così il DataContext quando si usa questo controllo in altri controlli. Prendendo il vostro legame, come ad esempio per l'utente:

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

una volta caricato e tutto il DataContext è impostata, cercherà il MyString percorso nel vostro controllo cosa BlueTextBox dovuto a voi impostare il DataContext ad esso. Immagino che questo non è il modo in cui hai inteso questo a funzionare;).

Soluzione:

Modificare il testo vincolante sia uno dei 2 attacchi:

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

o

Nome tua radice di controllo (o qualcosa di simile)

<UserControl x:Name="Root" 

{Binding ElementName=Root, Path=BlueText} 

E rimuovere il

DataContext = this; 

dal costruttore del vostro UserControl e dovrebbe funzionare come un fascino ..

0

Probabilmente è necessario aggiungere alla proprietà FrameworkPropertyMetadata dove specificare FrameworkPropertyMetadataOptions.AffectsRender e AffectsMeasure.

FrameworkPropertyMetadataOptions enumeration MSDN article

+0

provato a installare sia AffectsRender e AffectsMeasure, ma questo non ha avuto alcun effetto. Grazie. – RaoulRubin

2

Credo che in questo caso è necessario impostare la proprietà ElementName nel legame. Qualcosa di simile a questo:

<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

So che questo è un argomento vecchio, ma ancora.

citare anche il PropertyChangedCallback sul UIPropertyMetadata durante la registrazione del DP

Problemi correlati