2015-04-01 3 views
25

posso specificare DataContext in questo modo:Come specificare il tipo DataContext (ViewModel) per ottenere il controllo dell'associazione in fase di progettazione nell'editor XAML senza creare un oggetto ViewModel?

<Window ... > 
    <Window.DataContext> 
     <MainViewModel /> 
    </Window.DataContext> 
    ... 
</Window> 

E in questo caso WPF creerò un oggetto di tipo MainViewModel e assegnarlo alla proprietà DataContext della finestra (questo accade dentro il metodo di Window InitializeComponent()).

Ma cosa succede se il mio ViewModel non ha un costruttore predefinito. O se voglio inizializzare ViewModel e assegnarlo a DataContext dopo l'esecuzione di Window.InitializeComponent() (all'interno del costruttore di Window o dello stesso codice che istanzia la finestra) - in questo caso WPF crea un ViewModel (all'interno di InitializeComponent()), lo assegna a DataContext della finestra e quindi lo sovrascrivo con un'altra istanza di ViewModel (sono preoccupato per l'istanziazione di oggetti non necessaria qui).

Mi piacerebbe essere in grado di specificare solo un tipo di ViewModel, in modo da ottenere un avviso in fase di progettazione se ho sbagliato a digitare un nome di proprietà all'interno di {Binding} (o dopo aver rinominato la proprietà), o potrei andare alla dichiarazione facendo clic su (in XAML) su un nome di proprietà all'interno di {Binding PropertyName}.

Grazie per il vostro tempo impagabile.

risposta

23

Questa è la parte più difficile se fai il MVVM fai-da-te.

le opzioni, fondamentalmente:

Usa Dependency Injection

Si potrebbe iniettare il ViewModel nel costruttore 's Page/Window e assegnarlo al suo interno.

Questo ha però qualche svantaggio.

  • più difficile da usare visualizzare i modelli in fase di progettazione
  • Visualizzazioni non possono essere istanziati da XAML più

ViewModel Prima con Service

Farebbe risolvere i vostri ViewModels e navigazione fai tutta la tua navigazione tramite un servizio di navigazione. Nel tuo ViewModels si passa il INavigationService. È possibile navigare verso una vista usando il tipo ViewModel. Al suo interno istanziare ViewModel tramite Dipendenza Iniezione, quindi istanziare la Vista (basata su convenzioni di denominazione o tramite configurazione DI)

Questo è un po 'meglio, ma ancora non ti permetterà di istanziare le Viste in XAML. Un grande vantaggio è che permette facilmente di passare parametri al ViewModel (avendo i ViewModels implementano INavigationAware proprietà con NavigatedTo metodo, che è chiamato dopo l'istanza e passando il parametro a)

ViewModelLocator/Attached Property/Comportamento

Con questo, crei una proprietà associata, che puoi impostare su true (ad esempio, autowire) o su un tipo ViewModel (per avere più controllo sul ViewModel istanziato) e trovare e risolvere ViewModel e assegnarlo.

Fondamentalmente offre tutti i vantaggi sopra più la forma di istanziazione Vista.

L'ultimo che è fondamentalmente ciò che MVVM framework di Microsoft "Prism" fa (servizio di navigazione navigationService.Navigate("MyPage", myParameterForViewModel), DataContext esemplificazione e l'assegnazione da XAML via autowireing (in XAML:. prism:ViewModelLocator.AutoWireViewModel="True")

Detto questo, è meglio utilizzare un stagionato MVVM quadro che fa questo parti del cablaggio (anche se si decide di non utilizzare le classi di base, come BindableBase o come si chiama in tale quadro)

per quanto riguarda la fase di progettazione ViewModel/auto-completition per ViewModel:.

È possibile utilizzare gli attributi Design-Time di Blend per fare ciò. È necessario aggiungere prima i riferimenti all'assieme Blend. Quindi puoi aggiungere lo spazio dei nomi xmlns:d="http://schemas.microsoft.com/expression/blend/2008" nella tua pagina/vista.

Quindi è possibile associarlo alla pagina tramite d:DataContext="{d:DesignInstance my:DesignTimeViewModel, IsDesignTimeCreatable=True}. Notare d: prima di DataContext, questo è importante. Questo DataContext verrà utilizzato solo nella finestra di progettazione (Visual Studio XAML Designer o in Blend). Questo per evitare di interferire con il normale DataContext (senza il prefisso).

Esempio:

<Window x:Class="WpfApplication1.Window2" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:myApp="clr-namespace:WpfApplication1" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     mc:Ignorable="d" 
     d:DataContext="{d:DesignInstance myApp:Window2ViewModel, IsDesignTimeCreatable=True}"> 
    <Grid> 
     <TextBlock Text ="{Binding Test}"/> 
    </Grid> 
</Window> 

Se si utilizza interfacce per i vostri ViewModels, è abbastanza veloce per creare il design istanza, semplicemente avendo Visual Studio implementare tutte le proprietà di interfaccia e dare alcuni valori di default (per la proprietà in modo hai dati di esempio nel tuo ViewModel per verificare che i collegamenti funzionino correttamente).

Ciò richiede di creare ViewModels separati in fase di progettazione e ViewModels effettivi, che non è così male come sembra. Questo dà al tuo designer dell'interfaccia utente la possibilità di lavorare con esso, anche se il vero ViewModel non è ancora stato completato/implementato.

+0

Tseng, Grazie per la risposta. Con l'opzione "Use Dependency Injection" non ci sarà il controllo del binding in fase di progettazione, cioè nell'editor XAML otterrò l'avviso "Impossibile risolvere il simbolo XXX a causa di DataContext sconosciuto". Inoltre, non potrò fare clic sul nome di una proprietà all'interno di "{Binding PropertyName}" e saltare automaticamente su una dichiarazione di proprietà. – WpfNewbie

+1

Tseng, ho aggiunto un esempio (con estensione markup DesignInstance) nella tua risposta. Qualcuno lo approvi (non ho ancora abbastanza "potere"). Inoltre, non ho dovuto fare riferimento all'assemblaggio di Blend e ho dovuto aggiungere mc: Ignorable = "d" per renderlo compilabile. – WpfNewbie

+0

L'estensione di markup DesignInstance risolve il mio problema. Grazie. Contrassegnato come risposta. – WpfNewbie