2011-04-13 17 views
18

Tengo un ViewModel que necesita mostrar una ventana modal (usando ShowDialog()) al hacer clic en un botón. ViewModel capta el comando click, pero no quiero hacer window.ShowDialog() dentro de mi ViewModel. Sé que hay un DialogMessage en MVVM Light, pero eso se usa para mostrar los cuadros de mensaje, no las ventanas modales de WPF.Mostrar diálogo con MVVM Light toolkit

¿Alguna idea sobre cómo hacer esto?

+0

ver http://stackoverflow.com/questions/16993433/mvvm-light-wpf-binding-multiple-instances-of-a-window-to-a-viewmodel/16994523#16994523 – reggaeguitar

Respuesta

20

Debe usar la clase Messenger. En el View registre un mensaje para mostrar la ventana y luego, cuando necesite mostrarlo, llame al Send método de la clase Messenger.

se puede hacer algo como esto:

//do this in code behind file of your View 
Messenger.Default.Register<string>(this, ShowWindow); 

private void ShowWindow(string message) 
{ 
    // your logic here 
} 

// In the ViewModel 
Messenger.Default.Send(“Some text”); 
11

Esto es lo que yo uso para los diálogos personalizados con el Kit de herramientas de MVVM-Light.

Primero, defina estas cuatro clases en algún lugar de su aplicación. La clase MessageBase es parte del juego de herramientas.

public class ShowChildWindowMessage : MessageBase { } 
public class HideChildWindowMessage : MessageBase { } 
public class DisplaySomeContentMessage : MessageBase { } 
public class DisplaySomeOtherContentMessage : MessageBase { } 

En segundo lugar, necesita un control de ventana "hijo". Crear un archivo XAML con el siguiente contenido:

<Window x:Class="ChildWindowView" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    DataContext="{Binding Path=ChildWindowBinding, Source={StaticResource Locator}}" 
    Title="{Binding Path=CurrentContent.DisplayName}" 
    MinWidth="300" MinHeight="125" SizeToContent="WidthAndHeight" 
    ShowInTaskbar="False" WindowState="Normal" ResizeMode="NoResize" 
    WindowStartupLocation="CenterOwner" SnapsToDevicePixels="True"> 

<Grid> 
    <ContentPresenter Content="{Binding Path=CurrentContent}" /> 
</Grid> 

A continuación, añada lo siguiente al código subyacente de este archivo XAML:

public partial class ChildWindowView : Window 
{ 
    public ChildWindowView(Window owner) 
    { 
     InitializeComponent(); 
     Owner = owner; 

     Closing += (s, e) => 
     { 
      // window reused so just hide 
      e.Cancel = true; 
      Messenger.Default.Send(new HideChildWindowMessage()); 
     }; 
    } 

} 

En tercer lugar, añadir lo siguiente a la código- detrás de su archivo MainWindow.xaml:

public partial class MainWindowView : Window 
{ 
    private ChildWindowView m_childWindowView; 

    public MainWindowView() 
    { 
     InitializeComponent(); 
     Closing += (s, e) => ViewModelLocator.CleanUp(); 
     Loaded += (s, e) => 
     { 
      m_childWindowView = new ChildWindowView(this); 
     }; 

     Messenger.Default.Register<ShowChildWindowMessage>(this, (msg) => m_childWindowView.ShowDialog()); 
     Messenger.Default.Register<HideChildWindowMessage>(this, (msg) => m_childWindowView.Hide()); 
    } 
} 

En cuarto lugar, defina lo siguiente modelo de vista:

public class ChildWindowVM : ViewModelBase 
{ 
    private ViewModelBase m_currentContent; 
    public ViewModelBase CurrentContent 
    { 
     get { return m_currentContent; } 
     set 
     { 
      m_currentContent = value; 
      RaisePropertyChanged("CurrentContent"); 

      if (m_currentContent != null) 
      { 
       Messenger.Default.Send(new ShowChildWindowMessage()); 
      } 
     } 
    } 

    public ChildWindowVM() 
    { 
     Messenger.Default.Register<DisplaySomeContentMessage>(this, (msg) => CurrentContent = ViewModelLocator.SomeContentVm); 
     Messenger.Default.Register<DisplaySomeOtherContentMessage>(this, (msg) => CurrentContent = ViewModelLocator.SomeOtherContentVm); 
    } 
} 

En quinto lugar, se crea archivos XAML y modelos de vista del contenido que desea mostrar en su diálogo personalizado. En este ejemplo, mis modelos de vista de contenido se llamaron SomeContent y SomeOtherContent. Usted los reemplazaría con lo que quiera, por supuesto.

Por último, para que esto funcione debe enlazar sus contenidos modelos de vista de sus respectivos archivos XAML añadiendo lo siguiente a sus recursos de aplicación:

<DataTemplate DataType="{x:Type viewmodels:SomeContentVM}"> 
    <views:SomeContentView/> 
</DataTemplate> 

<DataTemplate DataType="{x:Type viewmodels:SomeOtherContentVM}"> 
    <views:SomeOtherContentView/> 
</DataTemplate> 

Ahora, una vez que todo este conjunto hasta que es muy fácil agregar contenido nuevo (modelos XAML y ver) que se pueden mostrar en la ventana de su hijo. Para visualizar el contenido, sólo tiene que llamar al mensaje apropiado utilizando la clase Messenger:

Messenger.Default.Send(new DisplaySomeContentMessage()); 

Avísame si necesito aclarar cualquier parte de esto para usted.

+0

pero ¿cómo hacer usted devuelve los resultados del diálogo con dicho enfoque? –

+0

El "resultado del diálogo" se maneja en el modelo de vista al que hace referencia la propiedad CurrentContent en ChildWindowVM. Por ejemplo, su SomeContentView.xaml tendría botones vinculados a algún RelayCommand en su clase SomeContentVM. Cuando se hace clic en un botón, el comando relacionado ejecuta el método asignado a él. En otras palabras, no es realmente lo mismo que un resultado de diálogo de un cuadro de mensaje, porque a este modelo de vista y vista ChildWindow no le importa el comportamiento de lo que se muestra. Es solo un contenedor de ventana para la vista real y el modelo de vista al que hace referencia la propiedad CurrentContent. – bugged87

+0

¡Interesante! Decidí tener una lista de ventanas secundarias en mi MainWindow.xaml (Dictionary ). En el método anterior ViewModels se crea dos veces, por lo que otro método debe tener un acoplamiento más estricto de ViewModels al agregar DataContext = "{Binding Content, RelativeSource = {RelativeSource FindAncestor, AncestorType = {x: Type ContentPresenter}}}" a DataTemplates –

0

Para todos los que quieren una solución muy simple y están bien con no-100% -clean-MVVM:
quería abrir un cuadro de diálogo de conexión de mi ventana principal e hizo la siguiente

Primera i di mi MainWindow un nombre:

<Window x:Name="MainWindow"> 

Entonces creó un comando en mi MainWindowViewModel:

public ICommand AddInterfaceCommand 
{ 
    get 
    { 
     return new RelayCommand<Window>((parentWindow) => 
     { 
      var wizard = new ConnectionWizard(); 
      wizard.Owner = parentWindow; 
      wizard.ShowDialog(); 
     } 
    } 
} 

até mi Butt en la ventana principal al comando y pasó la ventana misma (la ventana principal para el cuadro de diálogo):

<Button Command="{Binding AddInterfaceCommand}" CommandParameter="{Binding ElementName=MainWindow}">Add interface</Button> 

Eso es todo.

Advertencia: Obtener valores devueltos del Viewmodel of the Dialog podría ser difícil. No necesito esa característica.

0

Puede definir una interfaz y su implementación de la siguiente manera. Y, por supuesto, con el contenedor de inyección de dependencia, tienes que hacer algo así.

NInjectKernel.Bind<IMessageBoxService>().To<MessageBoxService>(); 

Su ViewModel se verá algo como esto.

private IMessageBoxService _MBService; 
    public DropboxSettingsViewModel(IDropboxService dbService, IMessageBoxService mbService) 
    { 
     if (dbService == null) 
      throw new ArgumentNullException("IDropboxService is null"); 

     _DropboxService = dbService; 

     if (mbService == null) 
      throw new ArgumentNullException("MessageBoxService is null"); 

     _MBService = mbService; 

    } 

Su método de ejecución de comando de clic sería el siguiente.

private void ConfigureDropboxExecute(object obj) 
    { 

     _MBService.Show("Error Occured Authenticating dropbox", "Dropbox Authentication", MessageBoxButton.OK, MessageBoxImage.Error, MessageBoxResult.OK); 

    } 


public interface IMessageBoxService 
{ 
    MessageBoxResult Show(string messageBoxText); 
    MessageBoxResult Show(string messageBoxText, string caption); 
    MessageBoxResult Show(Window owner, string messageBoxText); 
    MessageBoxResult Show(string messageBoxText, string caption, MessageBoxButton button); 
    MessageBoxResult Show(Window owner, string messageBoxText, string caption); 
    MessageBoxResult Show(string messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon); 
    MessageBoxResult Show(Window owner, string messageBoxText, string caption, MessageBoxButton button); 
    MessageBoxResult Show(string messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon, MessageBoxResult defaultResult); 
    MessageBoxResult Show(Window owner, string messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon); 
    MessageBoxResult Show(string messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon, MessageBoxResult defaultResult, MessageBoxOptions options); 
    MessageBoxResult Show(Window owner, string messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon, MessageBoxResult defaultResult); 
    MessageBoxResult Show(Window owner, string messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon, MessageBoxResult defaultResult, MessageBoxOptions options); 
} 

usando System.Windows;

public class MessageBoxService : IMessageBoxService 
{ 
    public MessageBoxResult Show(string messageBoxText) 
    { 
     return MessageBox.Show(messageBoxText); 
    } 

    public MessageBoxResult Show(Window owner, string messageBoxText) 
    { 
     return MessageBox.Show(owner, messageBoxText); 
    } 

    public MessageBoxResult Show(string messageBoxText, string caption) 
    { 
     return MessageBox.Show(messageBoxText, caption); 
    } 

    public MessageBoxResult Show(Window owner, string messageBoxText, string caption) 
    { 
     return MessageBox.Show(owner, messageBoxText, caption); 
    } 

    public MessageBoxResult Show(string messageBoxText, string caption, MessageBoxButton button) 
    { 
     return MessageBox.Show(messageBoxText, caption, button); 
    } 

    public MessageBoxResult Show(Window owner, string messageBoxText, string caption, MessageBoxButton button) 
    { 
     return MessageBox.Show(owner, messageBoxText, caption, button); 
    } 

    public MessageBoxResult Show(string messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon) 
    { 
     return MessageBox.Show(messageBoxText, caption, button, icon); 
    } 

    public MessageBoxResult Show(Window owner, string messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon) 
    { 
     return MessageBox.Show(owner, messageBoxText, caption, button, icon); 
    } 

    public MessageBoxResult Show(string messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon, MessageBoxResult defaultResult) 
    { 
     return MessageBox.Show(messageBoxText, caption, button, icon, defaultResult); 
    } 

    public MessageBoxResult Show(Window owner, string messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon, MessageBoxResult defaultResult) 
    { 
     return MessageBox.Show(owner, messageBoxText, caption, button, icon, defaultResult); 
    } 

    public MessageBoxResult Show(string messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon, MessageBoxResult defaultResult, MessageBoxOptions options) 
    { 
     return MessageBox.Show(messageBoxText, caption, button, icon, defaultResult, options); 
    } 

    public MessageBoxResult Show(Window owner, string messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon, MessageBoxResult defaultResult, MessageBoxOptions options) 
    { 
     return MessageBox.Show(owner, messageBoxText, caption, button, icon, defaultResult, options); 
    } 
} 
Cuestiones relacionadas