2010-05-20 21 views
6

Estoy creando un control de usuario wpf que está en el patrón mvvm. Así que tenemos: ver (sin código en el archivo codebehind), viewmodel, model, dataaccess files.cómo cargar wpf usercontrol en el patrón MVVM

que tienen MainWindow .xaml como un archivo de vista, lo que necesito para enlazar con MainWindowModel Cs.

Por lo general, en una aplicación wpf podemos hacer esto con el evento onStartUp en el archivo App.xaml. Pero en el control del usuario, ya que no tenemos App.xaml ... ¿Cómo lo logro?

Por favor, ayuda: (... Gracias de antemano !!!

Respuesta

16

Puede utilizar un ContentControl, con un DataTemplate a obligar a la UserControl (Ver) para el modelo de vista:

<DataTemplate DataType="{x:Type vm:MyViewModel}"> 
    <v:MyUserControl /> 
</DataTemplate> 

... 

<ContentControl Content="{Binding Current}" /> 

WPF escoger el DataTemplate automáticamente en función del tipo de la Content

+0

¿No necesitamos ninguna propiedad (propiedad de dependencia o propiedad normal) ... en la etiqueta de contenido? ... ¿O cómo "Actual" satisface lo mismo? – Relativity

+0

Hola Thomas, ¿Puedes darme una idea sobre la consulta anterior? – Relativity

+1

En el código anterior, 'Current' sería una propiedad del contexto de datos, de tipo' MyViewModel' –

2

he estado usando MVVM Light Toolkit que tiene una clase ViewModelLocator que se puede poner prop piedades a las ViewModels en A continuación, crear una referencia a la ViewModelLocator en su MainWindow.xaml este modo:.

<vm:ViewModelLocator x:Key="Locator" d:IsDataSource="True"/> 

En el panel de cuadrícula, o lo que sea que estés utilizando, a continuación, puede establecer los DataContext como este:

<Grid DataContext="{Binding MainWindowViewModel, Source={StaticResource Locator}}"> 
... 
</Grid> 

también podría ir con MEFedMVVM que potencialmente agrega un poco más de flexibilidad en términos de ser capaz de intercambiar diferentes implementaciones modelo de vista en la vista.

La flexibilidad en ambas bibliotecas es que no tiene que usar sus clases base de ViewModel si no lo desea; el ViewModelLocator y el MEFedMVVM pueden funcionar con cualquier clase.

2

Hay infinitas formas de hacerlo, que caen en una de las dos categorías: "ver primero" o "modelo primero".

En un modo de "vista en primer lugar" la vista (por ejemplo, su MainWindow) se crea primero y luego (por ejemplo, en el código subyacente) la vista de una instancia del modelo de vista y lo establece como su DataContext):

private void WindowLoaded(object sender, EventArgs args) 
{ 
    this.DataContext = ViewModelService.GetViewModelX(); 
} 

En En el modo "modelo primero", ViewModel está allí primero y luego instanciado la Vista.

// method of the viewmodel 
public void LoadView() 
{ 
    // in this example the view abstracted using an interface 
    this.View = ViewService.GetViewX(); 
    this.View.SetDataContext(this); 
    this.View.Show();  
} 

Los ejemplos que se dan aquí son sólo una forma de muchas. Puede consultar los diversos MVVM frameworks y ver cómo lo hacen.

+0

Gracias ... Lo veré – Relativity

+0

No dude en marcar la respuesta que desee como la respuesta aceptada. – bitbonk

+0

En el modelo MVVM ¿podemos tener código en el código detrás del archivo de una vista? – Relativity

0

Podemos utilizar ObjectDataProvider llamar a un método dentro de un ..as objeto sigue:

<ObjectDataProvider ObjectType="{x:Type local:TemperatureScale}" 
        MethodName="ConvertTemp" 
        x:Key="convertTemp"> 

¿Hay alguna forma de hacer lo mismo usando DataTemplate

5

Sé que esto es un viejo, respondió a la pregunta, pero tengo un enfoque diferente. Me gusta establecer relaciones implícitas en la aplicación.Archivo xaml:

<Application.Resources> 
    <DataTemplate DataType="{x:Type ViewModels:KioskViewModel}"> 
     <Views:KioskView /> 
    </DataTemplate> 
</Application.Resources> 

Con esto, no hay necesidad de configurar un DataContext en ningún lado.

ACTUALIZACIÓN >>>

En respuesta a la petición de @Vignesh Natraj, aquí hay una explicación más completa:

Una vez que haya configurado el DataTemplate en un elemento de Resources, se puede visualizar el KioskView en este ejemplo agregando una instancia de KioskViewModel en cualquier parte de su XAML. Esto podría estar llenando el MainWindow, o solo dentro de una sección particular de la pantalla. También puede alojar varias instancias del KioskViewModel en un ListBox y generará varias instancias KioskView.

Puede agregar una instancia de KioskViewModel a su XAML de varias maneras, dependiendo de sus requisitos. Una forma es declarar el espacio de nombres XML para el proyecto que contiene el archivo KioskViewModel.cs y simplemente agregar una instancia en un ContentControl a la página donde desea que aparezca su vista. Por ejemplo, si has tenido una UserControl llamada MainView y el archivo KioskViewModel.cs estaba en un espacio de nombres Kiosk.ViewModels, podría utilizar XAML básico como esto:

<UserControl x:Class="Kiosk.Views.MainView" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:ViewModels="clr-namespace:Kiosk.ViewModels"> 
    <UserControl.Resources> 
     <ViewModels:KioskViewModel x:Key="KioskViewModel" /> 
     <DataTemplate DataType="{x:Type ViewModels:KioskViewModel}"> 
      <Views:KioskView /> 
     </DataTemplate> 
    </UserControl.Resources> 
    <ContentControl Content="{StaticResource KioskViewModel}" /> 
</UserControl> 

que prefieren utilizar el patrón de diseño MVVM con WPF, por lo que tendría una clase de modelo de vista base que proporciona una funcionalidad útil, como la implementación de la interfaz esencial INotifyPropertyChanged. Luego tengo una propiedad llamada ViewModel en el modelo de vista principal (nivel superior) del tipo BaseViewModel. Esto me proporciona una buena manera de cambiar la propiedad ViewModel a cualquier modelo de vista que se haya derivado de BaseViewModel y, por lo tanto, de poder cambiar la vista asociada desde el modelo de vista.

Por ejemplo, en la clase MainViewModel.cs que está obligado a MainView hay un campo y bienes relacionados:

private BaseViewModel viewModel = new KioskViewModel(); 
public BaseViewModel ViewModel 
{ 
    get { return viewModel; } 
    set { viewModel = value; NotifyPropertyChanged("ViewModel"); } 
} 

Como se puede ver, que comienza como una instancia KioskViewModel, pero se puede cambiar a cualquier otra vista en cualquier momento en respuesta a la interacción del usuario. Para esta configuración, el XAML es muy similar, pero en lugar de declarar una instancia del modelo de vista en el elemento Resources, que se unen a la propiedad en el MainViewModel:

<UserControl x:Class="Kiosk.Views.MainView" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:ViewModels="clr-namespace:Kiosk.ViewModels"> 
    <ContentControl Content="{Binding ViewModel}" /> 
</UserControl> 

Tenga en cuenta que para este ejemplo, necesitaríamos para declarar dos (o más para que este enfoque sea útil) DataTemplate s en el archivo App.xaml:

<Application.Resources> 
    <DataTemplate DataType="{x:Type ViewModels:MainViewModel}"> 
     <Views:MainView /> 
    </DataTemplate> 
    <DataTemplate DataType="{x:Type ViewModels:KioskViewModel}"> 
     <Views:KioskView /> 
    </DataTemplate> 
</Application.Resources> 
+0

¿Puede explicarme cómo funciona esto? Intenté esto, pero no hay nada vinculado a mi punto de vista. Sé que es viejo, pero gracias. –

0

Es probable que pueda mirar a MSDN. Lo encuentro como un buen recurso, aunque no explica cómo usar los controles de usuario, encontrará la salida.