2010-09-13 16 views
8

Ho riscontrato un problema con la chiamata di un metodo su un UserControl. Ascoltami:Chiamare un metodo di un UserControl in MVVM

  1. Ho un UserControl someControl in SomeView.xaml

  2. DataContext di SomeView.xaml è SomeViewModel.cs

  3. Voglio essere in grado di chiamare someControl.DoStuff() in qualche modo, da qualche parte.

  4. DoStuff non è specifica interfaccia utente (avrei potuto appena chiamato DoStuff dal code-behind di SomeView.Xaml.Cs se fosse interfaccia utente specifica, ma in questo caso, potrebbe non essere.)

Qualche idea?

Grazie!

risposta

5

Probabilmente non ti piacerà la risposta, ma il tuo ViewModel non dovrebbe conoscere l'interfaccia utente. Se hai un metodo non UI sul tuo UserControl, probabilmente è nel posto sbagliato.

L'unica cosa che potrei pensare è che potresti voler implementare qualche tipo di messaggio (come quello che hanno in MVVM Light) che potrebbe attivare l'esecuzione.

È questo o ripensare a come hai architettato il tuo codice.

+0

Capisco da dove vieni e credimi, ci ho pensato. Ma arriva un momento in cui hai davvero bisogno di chiamare un metodo. Ad esempio, il metodo sul controllo utente potrebbe essere esposto e potrei non avere la fonte per l'usercontrol, quindi non posso modificarlo per soddisfare il mio caso. –

+0

+1 per il suggerimento però, hai ragione, ViewModel non dovrebbe avere conoscenza della vista. –

+0

In tal caso, vai al codebehind, forse? – Robaticus

0

In MVVM design, l'idea generalmente non è di avere QUALSIASI codice in UserControl (il file xaml.cs) (in un mondo ideale). Tutte le interazioni tra l'interfaccia utente e il ViewModel devono essere gestite tramite comandi e binding ... quindi perché hai bisogno di DoStuff nel controllo utente?

Si potrebbe avere qualcosa di simile

<Button Command="{Binding myCommandOnTheDataContextViewModel}" Content="{Binding somePropertyOnTheViewModel}" /> 
3

Sembra che si desidera DoStuff accada in risposta ad alcuni dati o logica nel vostro VM, nel qual caso il metodo più pulito sarebbe probabilmente quella di utilizzare un evento originario della la tua VM e gestita da DoStuff. Se il trigger è più simile a una modifica dello stato, è possibile associare i dati della VM appropriata a una nuova proprietà di dipendenza sul proprio UserControl e chiamare DoStuff dal gestore di modifiche del DP.

0

Forse il tuo UserControl dovrebbe essere davvero una vista, che quindi dovrebbe avere un ViewModel, che conterrebbe il metodo DoStuff(). SomeViewModel avrà istanziato (sono in leasing in modo casuale per essere istanziato) SomeControlViewModel, e quindi essere in grado di chiamare un metodo su di esso.

0

Se si dispone di un approccio View-first (e la VM è istanziata come Risorsa in XAML) è possibile utilizzare alcuni eventi normali per collegare il metodo Controllo DoStuff con alcuni eventi su VM (su evento Loaded).

0

Se il metodo DoStuff(); fa qualche logica specifica UI quindi il metodo è nel posto giusto. Quando non lo è, dovrebbe trovarsi in un altro oggetto (ad esempio SomeViewModel).

SomeViewModel è autorizzato a richiamare un metodo su SomeView quando è separato tramite un'interfaccia. Come questo può essere realizzato è mostrato dal WPF Application Framework (WAF).

1

Uno il SO rispondere per raggiungere tale scopo dal disaccoppia la conoscenza del ViewModel in merito a View è utilizzando i delegati di azione risposta da Merthere

Introdurre il suo codice qui, in caso di rottura di collegamento per caso.

class MyCodeBehind 
{ 
    public MyCodeBehind() 
    { 
     Action action = new Action(()=> this.SomeMethodIWantToCall()); 
     var myVM = new MyVM(action); // This is your ViewModel 
     this.DataContext = myVM; 
    } 

    private void SomeMethodIWantToCall(){...} 
} 

class MyVM 
{ 
    private Action action; 

    public MyVM(Action someAction) 
    { 
     this.action = someAction; 
    } 

    private void SomeMethodInVM() 
    { 
     this.action(); // Calls the method SomeMethodIWantToCall() in your code behind 
    } 
} 
Problemi correlati