Show MessageBox using IResult

Topics: Actions & Coroutines, Getting Started
Jan 5, 2012 at 8:04 PM

Hello,

I read the article on how to use IResult in showing dialogs etc. I am developing a WPF application using Caliburn Micro. I have a ViewModel with following method:

public void SavePlan(bool saveActivity=false)
        {
            try
            {                
                //do something


            }
            catch (Exception ex)
            {
                GlobalDataAccessAdapter.Adapter.Rollback();
                _log.Error(ex);
               
            }

        }

I want to show messagebox only when in catch block. How do I do that using IResult and co-routines? From what I understand, I will have to modify the above method as follows:

 

public IEnumerable<IResult> SavePlan(bool saveActivity=false)
        { var messenger = new Messenger();
            try
            {                
                  //do something
               
            }
            catch (Exception ex)
            {
                GlobalDataAccessAdapter.Adapter.Rollback();
                _log.Error(ex);
               
            }

        }

Based on earlier discussion http://caliburnmicro.codeplex.com/discussions/231507, I created the Messenger class that implements IResult.

But dont know how to proceed further. Any ideas will be very helpful!!

 

Thanks

 

Apurva

Jan 6, 2012 at 7:50 AM

You do the following:

public void SavePlan(bool saveActivity=false)
        {
            try
            {               
                //do something
            }
            catch (Exception ex)
            {
                //do something and call function to show message box
               Coroutine.BeginExecute( DoShowMessageBox( yourExceptionOrWhatever ).GetEnumerator() );
            }
  }

and e.g.

public IEnumerable<IResult> DoShowMessageBox( string whatever )
{
        //your IResult implementation, e.g. :

   var openDialog = ShowDialog.Of<MyViewModel>();
   yield return openDialog;
   //use result

}

In my projects I use the ShowDialog implementation discussed here: http://caliburnmicro.codeplex.com/discussions/250303

and I think it's very comfortable.

Jan 6, 2012 at 10:15 PM

Thank you so much for this help!! So do I need to create a separate view for the MyViewModel which only shows the dialog? How do I show simple message box with this?

 

Thanks

Jan 10, 2012 at 9:34 AM
Edited Jan 10, 2012 at 9:43 AM

Yes, I have my own implementation of message boxes since the default silverlight message box is really limitated ( what would you do if you need retry, abort, yes, no, etc. buttons? ).

A message box interface (for a message box view model) may look like this:

public interface IMessageBox : IScreen 
{ 
   CommonEnums.MessageBoxResults Result { get; set; } 
   CommonEnums.MessageBoxTypes Type { get; set; } 
   string Message { get; set; } 
   void Init( CommonEnums.MessageBoxTypes Type, string displayName, string message ); 
} 

and the enums may look like this:

public enum MessageBoxTypes
 {
         OK,
         OKCancel,
         AbortRetryIgnore,
         YesNoCancel,
         YesNo,
         RetryCancel
}

public enum MessageBoxResults
{
         Cancel,
         OK,
         Abort,
         Retry,
         Ignore,
         Yes,
         No
 }

If you are working with MEF, just import a property of type IMessageBox

[Import]
public IMessageBox MessageBox { get; set; }

and use ShowDialog like this (I use Init-methods for my message box view model):

MessageBox.Init( Common.Enums.CommonEnums.MessageBoxTypes.OK, "header", "message" );
var openDialog = ShowDialog.Of<IMessageBox>();
yield return openDialog;

In my message box view I have stack panels for the button panel on which I set the Visibility property depending on the message box type like this:

...
<Grid Margin="2">
     <StackPanel Visibility="{Binding BtnOkVisible, Mode=TwoWay, Converter={StaticResource VisibilityConverter}}" HorizontalAlignment="Right">
           <Button Content="OK" cal:Message.Attach="OK()" Height="30" HorizontalAlignment="Center" VerticalAlignment="Center" Width="110" Margin="5" />
           <StackPanel>
           <StackPanel Visibility="{Binding BtnOkCancelVisible, Mode=TwoWay, Converter={StaticResource VisibilityConverter}}" HorizontalAlignment="Right">
               <Button Content="OK" cal:Message.Attach="OK()" Height="30" HorizontalAlignment="Center" VerticalAlignment="Center" Width="110" Margin="5" />
               <Button Content="Cancel" cal:Message.Attach="Cancel()" Height="30" HorizontalAlignment="Center" VerticalAlignment="Center" Width="110" Margin="5" />
           </StackPanel>
...

 Hope this helps (I don't know if there are simpler implementations but for me it does the job)

Jan 10, 2012 at 2:51 PM

Thank you so much again. Appreciate your help. This solves my issue!!

Feb 14, 2012 at 4:23 PM
Edited Feb 14, 2012 at 5:04 PM

I tried using this approach for showing message box as instructed in last thread. However when I use following code to show dialog from Mapping View Model-

 

 

 MessageBox.Init(Helpers.MessageBoxTypes.YesNo, "Confirm Delete Plan", "Are you sure you want to delete selected plan?");
                var openDialog = ShowDialog.Of<IMessageBox>();
                yield return openDialog;

 

I always end up with default dialog with no message and just an OK button (which is the first vale in MessageBoxTypes enum). Thats probably because ShowDialog is using Ioc to get instance? I have wired up my bootstrapper as follows:

 

x.For<IMessageBox>().Use<MessageBoxViewModel>();

Here is my ViewModel:

public class MessageBoxViewModel : Screen, IMessageBox
    {
        #region IMessageBox Members

        public Helpers.MessageBoxResults Result{get; set;}
        public Helpers.MessageBoxTypes Type{get; set;}
        public string Message{get; set;}

        public void Init(Helpers.MessageBoxTypes Type = Helpers.MessageBoxTypes.YesNo, string displayName="Confirm", string message="Are you sure?")
        {
            this.Message = message;
            this.Type = Type;
            this.DisplayName = displayName;
            
        }

        #endregion

        public bool BtnOKVisible
        {
            get { return Type == Helpers.MessageBoxTypes.OK; }
        }

        public bool BtnOKCancelVisible
        {
            get { return Type == Helpers.MessageBoxTypes.OKCancel; }
        }

        public bool BtnYesNoVisible
        {
            get { return Type == Helpers.MessageBoxTypes.YesNo; }
        }

        public void Ok()
        {
            Select(Helpers.MessageBoxResults.OK);
        }

        public void Cancel()
        {
            Select(Helpers.MessageBoxResults.Cancel);
        }

        public void Yes()
        {
            Select(Helpers.MessageBoxResults.Yes);
        }

        public void No()
        {
            Select(Helpers.MessageBoxResults.No);
        }

        void Select(Helpers.MessageBoxResults option)
        {
            Result = option;
            TryClose();
        }
    }


 The only way I can get it working is by creating singleton as follows-
x.For<IMessageBox>().Singleton().Use<MessageBoxViewModel>();

However I am not sure if this is a good practice.
Is there something I am missing?

 

 

Thanks

 

Apurva