none
Tratamiento de ventanas respetando el patron mvvm en WPF RRS feed

  • Pregunta

  • Hola amigos del foro, en esta oportunidad mas que una pregunta voy a intentar realizar un aporte.

    Algo bastante complicado de encarar es el tratamiento de dialogos respetando las premisas del patron mvvm. Cuando hablo de dialogos me refiero a cuadros de dialogo, los típicos messagebox y tambien habrir y cerrar ventanas (views).

    Cuando encare este tema, despues de numerosas pruebas y errores, fui llegando a lo que creo q posiblemente sea una buena solucion, espero que con esto se habra algun debate a ver si les parece bien, mal, regular y como lo podemos mejorar.

    Al punto:

    Ya como todos sabemos, en nuestro viewmodel no deberiamos hacer llamados a un messagebox directamente ya que estariamos violando el principio de que en el viewmodel no debemos referenciar al system.windows ni a referenciar directamente a una vista y por supuesto para mantener desacoplado nuestro viewmodel y aferrarnos a la premisa que una clase solo debe hacer lo suyo (una de las premisas de SOLID) nuestro viewmodel debe quedar desligado de esa obligacion.

    Bueno... veamos mi posible solucion:

    Para lograr esto, voy a declarar una clase que la llamare ServicioDialogo e implementara su respectiva interfaz:

    public interfase IServicioDialogo

    {

    string MostrarMensaje(string contenido, string titulo, string botones, string imagen);

    void MostrarVentana(ViewModelBase viewModel);

    void CerrarVentana(string nombreVentana);

    }

    Ahora la implementacion de esta interfaz:

    public class ServicioDialogo : IServicioDialogo

    {

    #region Miembros

    private static IServicioDialogo _instancia;

    #endregion

    #region Miembros de IServicioDialogo

    public static IServicioDialogo Instancia

    {

    get

    {

    if(_instancia == null)

    _instancia = new ServicioDialogo(); //Devolvemos una instancia de la clase ServicioDialogo si no existe.

    return _instancia;

    }

    internal set

    {

    _instancia = value;

    }

    }

    public string MostrarMensaje(string contenido, string titulo, string botones, string imagen)

    {

    //Retornamos el mensaje, los botones y la imagen se obtienen con los metodos privados ObtenerBotones y ObtenerImagen.

    return MessageBox.Show(contenido, titulo, ObtenerBotones(), ObtenerImagen())).ToString();

    }

    public void MostrarVentana(ViewModelBase viewModel)

    {

    //Aca simplemente utilizo una ventana a la que denomine VentanaContenedora y pasando como argumento un viewmodel se lo asigno al

    //DataContext de la VentanaContenedora. En la VentanaContenedora en el xaml a la propiedad Content de un ContentControl la asigno asi: //<ContentControl Content = "{Binding}" />. Utilizo DataTemplates para mapear los viewmodels a las views y cada vista es simplemente

    //un user control.

    var ventana = new VentanaContenedora()

    {

    DataContext = viewModel;

    };

    ventana.Owner = Application.Current.MainWindow;

    ventana.ShowInTaskbar = False;

    ventana.ShowDialog(); 

    }

    public void CerrarVentana(string nombreVentana)

    {

    //Se busca el las instancias de ventanas que haya en la aplicacion la que corresponda con el nombre que le pasemos. Una vez hayamos obtenido

    //la instancia de la ventana, simplemente llamamos al metodo Close().

    var ventana = Application.Current.Windows.OfType<Window>().Where(w => w.Name == nombreVentana).SingleOrDefault<Window>();

    ventana.Close();

    }

    #endregion

    #region Metodos privados

    private MessageBoxButton ObtenerBotones(string botones)

    {

    MessageBoxButton _botones = null;

    switch (botones)

    {

    case "OK":

    _botones = MessageBoxButton.OK;

    break;

    case "YesNo":

    _botones = MessageBoxButton.YesNo;

    break;

    case "OKCancel":

    _botones = MessageBoxButton.OKCancel;

    break;

    case "YesNoCancel":

    _botones = MessageBoxButton.YesNoCancel;

    break;

    }

    return _botones;

    }

    private MessageBoxImage ObtenerImagen(string imagen)

    {

    MessageBoxImage _imagen = null;

    switch(imagen)

    {

    case "Error":

    _imagen = MessageBoxImage.Error;

    break;

    case "Hand":

    _imagen = MessageBoxImage.Hand;

    break;

    case "Information":

    _imagen = MessageBoxImage.Information;

    break;

    case "Question":

    _imagen = MessageBoxImage.Question;

    break;

    case "Warning":

    _imagen = MessageBoxImage.Warning;

    break;

    case "Stop":

    _imagen = MessageBoxImage.Stop;

    break;

    case "Exclamation":

    _imagen = MessageBoxImage.Exclamation;

    break;

    case "Asterisk":

    _imagen = MessageBoxImage.Asterisk;

    case "None":

    _imagen = MessageBoxImage.None;

    break;

    }

    return _imagen;

    }

    #endregion

    Bueno ahora en nuestro viewmodel podemos usar estos metodos de la siguiente forma:

    Por ejemplo para cerrar la vista actual:

    if(ServicioDialogo.Instancia.MostrarMensaje("Esta seguro que desea cerrar la ventana?", "Cerrar ventana", "YesNo", "Question") == "Yes")

    ServicioDialogo.Instancia.CerrarVentana("Mi ventana");

    }

    De esta manera en nuestro viewmodel jamas referenciamos ni a System.Windows, ni a nuestra view. No hacemos llamados directos a MessageBox, simplemente utilizamos nuestra clase ServicioDialogo a quien le asignamos la responzabilidad de mostrar dialogos, abrir y cerrar ventanas.

    Bueno espero que el aporte haya sido de utilidad y comenten a ver que les parecio.

    Un saludo grande gente amante del software!!!



    • Editado ArielNet viernes, 15 de febrero de 2013 22:58
    viernes, 15 de febrero de 2013 22:34