2010-04-18 16 views
5

Sto provando a far funzionare la mia prima app WPF utilizzando MVVM e ho riscontrato un piccolo problema di associazione.WPF: impostazione DataContext di un UserControl con Binding non funzionante in XAML

La messa a punto è che ho una visione & ViewModel che detiene i dettagli utente (il genitore), e per cercare di mantenere le cose semplici ho messo una sezione di quella vista in una vista separata & ViewModel (il bambino). La vista figlio è definita come UserControl.

Il problema riscontrato è come impostare DataContext della vista figlio (UserControl). Il mio genitore ViewModel ha una proprietà che espone il bambino ViewModel, in questo modo:

class ParentViewModel: INotifyPropertyChanged 
{ 
    public ChildViewModel childViewModel { get; set; } 
    //... 
} 

In XAML per la mia vista padre (che ha il DataContext insieme al ParentViewModel), cerco di impostare il DataContext della vista del bambino come segue:

<views:ChildView 
    x:Name="ChildView" 
    DataContext="{Binding childViewModel}"/> 

Tuttavia, questo non funziona. Il DataContext della vista figlio è impostato sullo stesso DataContext della vista padre (ad esempio ParentViewModel), come se non lo avessi impostato. Ho anche provato a installare il DataContext nel bambino visualizzare stessa, che anche non funziona:

<UserControl x:Class="DietRecorder.Client.View.ChildView" 
    DataContext="childViewModel" 

ho trovato un paio di modi per aggirare questo. Dal punto di vista del bambino, posso legare tutto includendo il ChildViewModel nel percorso:

<SomeControl Visibility="{Binding Path=childViewModel.IsVisible}"> 

ma io non voglio la vista bambino ad avere questo livello di consapevolezza della gerarchia. Impostazione del DataContext nel codice funziona anche - tuttavia, che devo fare questo dopo che mostra la vista padre, altrimenti il ​​DataContext appena viene sovrascritto quando chiamo Show():

parentView.Show(); 
parentView.ChildView.DataContext = parentViewModel.childViewModel; 

Questo codice mi fa anche sentire a disagio, cosa con la violazione LOD e tutti.

E 'solo il DataContext che sembra essere il problema - posso legare le altre cose nel bambino, per esempio ho provato vincolante il FontSize a una proprietà int solo per testarlo:

<views:ChildView 
    x:Name="ChildView" 
    FontSize="{Binding Path=someVal}"/> 

e che funziona bene.

Ma sono sicuro che il DataContext dovrebbe funzionare: ho visto esempi simili di questo genere di cose. Ho perso qualcosa di ovvio qui? C'è una ragione per cui questo non funzionerà? C'è un errore di ortografia da qualche parte? (Ho ribattezzato le cose per il tuo beneficio, quindi non sarai in grado di aiutarmi comunque).

Qualsiasi pensiero benvenuto.

Modifica

Rivedere di nuovo questo codice, sembra che abbia fatto un errore da qualche parte, come il seguente XAML in vista padre risulta attualmente al lavoro:

<views:ChildView 
    x:Name="ChildView" 
    DataContext="{Binding childViewModel}"/> 

Sono non sono sicuro del motivo per cui non sono riuscito a farlo funzionare in origine, o cosa avrei potuto cambiare per farlo funzionare. Forse era il problema INotifyPropertyChanged come suggerisce una delle risposte. Oh bene, in avanti e verso l'alto ..

risposta

2

Sospetto che sia perché la proprietà childViewModel non genera l'evento PropertyChanged. Quando il bind viene valutato, è possibile che questa proprietà sia nullo (nel qual caso DataContext tornerà semplicemente a quello del genitore). Quando il childViewModel viene istanziato in seguito, non viene generato alcun evento PropertyChanged e l'associazione non viene mai informata dell'esistenza di un DataContext.

Provare ad aumentare l'evento PropertyChanged nella proprietà childViewModel.

Cheers, Laurent

+0

Buon pensiero, ma nessuna gioia ho paura. Stavo pensando che potrebbe essere qualcosa a che fare con l'ordine, ma il bambino viewModel dovrebbe essere disponibile quando avviene l'associazione - e funziona quando imposto la dimensione del carattere utilizzando la proprietà int, che accade nello stesso momento, e che non lo fa t usare PropertyChanged. –

2

stavo cercando la stessa cosa e ho trovato un modo per farlo. Fondamentalmente, ho legato il DataContext del bambino al DataContext di qualche genitore (la finestra) utilizzando

DataContext="{Binding ElementName=_topLevel, Path=DataContext.childViewModel}" 

dove ho impostato x:Name="_topLevel" su qualche controllo padre (la finestra).

Ho provato a utilizzare RelativeSource/FindAncestor anziché ElementName ma non ha funzionato, ma probabilmente era colpa mia.

Mi sento come un hack, ma è meglio che legarsi al modello di vista di livello superiore.

+0

Anche se non l'ho provato, dovrebbe funzionare, quindi ti darò +1 per lo sforzo dopo tutto questo tempo - ma questa soluzione ha lo stesso problema di una delle soluzioni che ho suggerito sopra, cioè che il bambino sa del genitore. Questo è solo un cattivo odore o un problema reale, a seconda che si utilizzi il bambino in diverse visualizzazioni genitore o meno. Quando ho controllato il mio codice per questa risposta, ho scoperto che ora funziona, anche se non sono sicuro del perché - vedere la modifica per i dettagli. –

2

Questa non è una risposta alla domanda, ma potrebbe aiutare gli altri nelle stesse circostanze.

mi ha colpito proprio questo problema e ha scoperto che l'approccio

parentView.ChildView.DataContext = parentViewModel.childViewModel; 

lavorato (anche se ho trovato che ha funzionato prima di fare Show()), ma aveva gli stessi scrupoli su di esso, come l'interrogante originale in modo provato il

DataContext="{Binding ElementName=_topLevel, Path=DataContext.childViewModel}" 

approccio, che sembrava funzionare. Ma poi ho provato a tornare al codice originale e all'XAML originale, e ora ha funzionato anche all'improvviso. Ciò rispecchia il comportamento del questionario originale in cui l'autore pensava di aver commesso un errore da qualche parte poiché sembrava che XAML iniziasse a funzionare senza una ragione ovvia.

L'unico cambiamento che posso vedere è che Visual Studio mostra ora i dati di esempio in UserControl in fase di progettazione, quindi ha memorizzato alcuni dati di esempio da qualche parte, e sembra che funzioni. Non sono sicuro di quale delle due modifiche abbia comportato il verificarsi, sfortunatamente.

L'aspetto dei dati di esempio mi fa chiedere se il problema è collegato all'uso di d: DataContext, che ho nei file XAML padre e figlio, ma si tratta solo di speculazioni.

Problemi correlati