2010-11-16 5 views
11

Estoy trabajando en una aplicación MVVM wpf y necesito mostrar varios cuadros de diálogo con ok cancel. He visto pocos en la red, pero la mirada es demasiado complicada o puede ser que yo esté luchando.Aceptar cancelar Dialog MVVM Pattern wpf.¿Cómo puedo hacerlo?

he notado que muchos de los que usan "IDialogService"

Puede alguien que me señale un enlace o tiene un fragmento útil sobre cómo implementar un diálogo utilizando un patrón MVVM?

muchas gracias

+0

Algunos contextos pueden ser útiles antes de intentar una respuesta: ¿por qué usa MVVM?¿Trabajas en equipo o solo? ¿Pruebas por unidad tu capa de presentación? En caso afirmativo, ¿está familiarizado con los marcos de burla? –

+0

¿De qué estás teniendo problemas? (¿Mostrar el diálogo? ¿Cerrar el diálogo? ¿Conectar el cuadro de diálogo a su ViewModel? ¿Otro?) Además, ¿está utilizando un marco MVVM y, de ser así, cuál? –

+0

Lo siento. Pensé que era una pregunta muy genérica. No hay código. Estoy usando Moq como framework de Mocking. De hecho, me gustaría probarlo en una unidad. En el proyecto real en el trabajo, tengo una arquitectura desconectada usando PL-SL-BL-DAL. No quería confundir a las personas o hacer que la pregunta fuera complicada. Simplemente quería y quería ayuda para mostrar un diálogo usando un patrón MVVM. No puedo usar ninguno de los frameworks que hay allí. Nosotros usamos uno interno. Una vez que agarro el contexto y puede transferirlo a mi proyecto real. – user9969

Respuesta

10

aquí es un cuadro de diálogo de barebones con los botones Aceptar y Cancelar. He incluido el XAML, Ver y modelo de vista:

XAML:

<Window 
    x:Class="TestProject.Views.OKCancelDialog" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
    Title="Window Title" 
    Height="300" 
    Width="600" 
    WindowStartupLocation="CenterOwner" 
    WindowStyle="ToolWindow" 
    ResizeMode="CanResize" 
    UseLayoutRounding="True" 
    TextOptions.TextFormattingMode="Display"> 

    <Grid> 
     <Button 
      Name="OKButton" 
      Content="OK" 
      Height="23" 
      HorizontalAlignment="Right" 
      Margin="0,0,93,12" 
      VerticalAlignment="Bottom" 
      Width="75" 
      Click="OKButton_Click" 
      IsDefault="True" 
      Command="{Binding OKButtonCommand}" /> 

     <Button 
      Name="CancelButton" 
      Content="Cancel" 
      Height="23" 
      HorizontalAlignment="Right" 
      Margin="0,0,12,12" 
      VerticalAlignment="Bottom" 
      Width="75" 
      IsCancel="True" /> 
    </Grid> 
</Window> 

Codebehind:

using System.Windows; 
using TestProject.ViewModel; 

namespace TestProject.Views 
{ 
    public partial class OKCancelDialog : Window 
    { 
     private readonly OKCancelViewModel viewModel; 

     //I use DI to inject the ViewModel into the View 
     //This will allow you to use the view for different ViewModels if you need to. 
     //Create an Interface for your ViewModel to implement to make ViewModel unit testing 
     //easier. Testing frameworks such as rhino mock require Interfaces to test methods 
     //in a class under test and it allows you to use an IoC Container to create the 
     //ViewModel for you.     
     public OpenReturnDialog(IOKCancelViewModel viewModel) 
     { 
      InitializeComponent(); 
      this.viewModel = viewModel; //Do this if you need access to the VM from inside your View. Or you could just use this.Datacontext to access the VM. 
      this.DataContext = viewModel; 
     } 

     private void OKButton_Click(object sender, RoutedEventArgs e) 
     { 
      DialogResult = true; 
     } 

    } 
} 

modelo de vista

using Microsoft.Practices.Composite.Presentation.Commands; 


namespace TestProject.ViewModel 
{ 
    public class OKCancelViewModel 
    { 
     public OKCancelViewModel() 
     { 
      OKButtonCommand = new DelegateCommand<object>(HandleOKButtonCommand, CanExecuteOKButtonCommand); 
     } 

     public DelegateCommand<object> OKButtonCommand { get; private set; } 

     public void HandleOKButtonCommand(object obj) 
     { 
      //Here is where your code for OK button clicks go. 

     } 

     public bool CanExecuteOKButtonCommand(object obj) 
     { 
      //Put code to determine when the OK button will be enabled/disabled. 
     } 

     //You may want to add a command for the Cancel button also if you have a need to 
     //enable/disable the cancel button 
     //The command will look just like the OK button command above. 
    } 
} 

Ahora, lo más probable es que desee que su ViewModel implemente INotifyPropertyChanged en caso de que tenga otros controles en su UI que se vincularán a las propiedades en ViewModel.

Espero que esto ayude ...

+0

Gracias por su respuesta con el código. Acabo de crear un proyecto de cabeceo y poner su código en él. Tengo 2 ventanas. Tu OKCancelDialog y MainWindow. MainWindow tiene un botón "Launch Dialog. ¿Cómo lo haces con tu código? – user9969

+0

Bueno, allí es donde difieren las opiniones de las personas. Todavía tengo que encontrar una mejor práctica para eso, así que te diré cómo lo hago. La ventana principal también debería tener una máquina virtual con un "LaunchDialogCommand", al igual que los comandos en mi código anterior. Incluido en el "HandleLaunchDialogCommand" tiene código para crear el OKCancelViewModel y OKCancelView. Algo como esto: var dlg = new OKCancelView (new OKCancelViewModel ()); Ahora, aquí es donde entran muchas opiniones diferentes. Puede llamar a OKCancelView.ShowDialog(); pero como se encuentra dentro de una VM, la mayoría de las personas sienten que es incorrecto llamar a ShowDialog() dentro de una VM. – ihatemash

+0

La mayoría de las personas en ese caso, plantee un evento al que alguna otra clase se suscriba y llame a ShowDialog(). Estoy un poco tranquilo, por lo que generalmente solo llamo a ShowDialog() dentro de ViewModel. Eche un vistazo a este enlace: http://stackoverflow.com/q/1730290/195356 – ihatemash

7

creo que todo el mundo que utiliza un IDialogService o en realidad crea sus propios cuadros de diálogo ha terminado el problema de ingeniería. Realmente me gusta el enfoque simplista de usar Funcs. Aquí hay un ejemplo. Primero se debe agregar esto a su modelo de vista:

public abstract class ViewModelBase : INotifyPropertyChanged 
{ 
    /** Other ViewModel Code *// 

    public Func<string, string, bool> OkCancelDialog { get; set; } 
} 

Luego, cuando se instancia la clase derivada de su modelo de vista, que acaba de adjuntar el siguiente código: (Me suelen hacer esto en el arranque como Program.cs)

var myVM = new SomeSuperViewModel(); 
myVM.OkCancelDialog = (msg, caption) => MessageBox.Show(msg, caption, MessageBoxButton.OkCancel) == MessageBoxResult.OK; 

En su código modelo de vista real, todo lo que tiene que hacer es llamar:

if (OkCancelDialog("Some crazy message.", "Caption")) 
    //do something if true 
else 
    //else do something if false 

En las pruebas unitarias se puede hacer esto:

var myVMToTest = new SomeSuperViewModel(); 
myVMToTest.OkCancelDialog = (msg, caption) => true; //could be false too if you need to test that functionality. 

Prefiero este enfoque, ya que es simple y fácil de probar. ¿Qué piensan los demás?

0

que te pueden echar un vistazo a la aplicación (EmailClient) muestra modelo de vista de la WPF Application Framework (WAF). Muestra cómo escribir diálogos personalizados con MVVM y muestra cómo puede usar el MessageBox sin violar el patrón de MVVM.

0

¿Qué pasa con sólo llamar System.Windows.MessageBox.Show() desde el código de su modelo de vista

por ejemplo,

public bool GetConfirmation(string Message, string Caption) 
{ return MessageBox.Show(Message, 
         Caption, 
         System.Windows.MessageBoxButton.OKCancel, 
         System.Windows.MessageBoxImage.Question, 
         System.Windows.MessageBoxResult.Cancel) == System.Windows.MessageBoxResult.OK; } 
+0

Supongo que el OP está buscando para probar. –