Saturday, October 9, 2010

Closing View From ViewModel Using MVVM

In this post I will show you how to close the view from the view model.The problem was to close the window or the dialog box when user has done the save/update operation in the form. So In normal situation when there is no MVVM involved then we can close the window or dialog box when the record is saved in the data base. In case of window we close the window and in case of dialog box we will use the DialogResult property to close the dialog box. Let us start with the example of how to close the dialog or window from viewModel using MVVM.
I have modal, view and view modal folder to keep modal , view and view modal classes separate and also have some other folder to keep the other stuff in separate folder. If you want to learn basic of the MVVM then you can read the following article.Let us discuss the code and the steps which are used to close the view from the view modal in MVVM.
Here is my code which is listed in the List 1 added at the window tag. First I have add the reference of the namespace which define the attached property to close the dialog or window. Then I have Bind the attache property with the property defined in the view model.


xmlns:properties="clr-namespace:Close_View_From_ViewModel.AttachedProperty"   properties:CloseDialog.DialogResult="{Binding IsDialogClose}"
List 1

Next is the attached property which is used to close the dialog or window.So here is the attached property which is used to close the window or dialog box depending on if you are using the show or showDialog function to open the the window.


public static class CloseDialog { public static readonly DependencyProperty DialogResultProperty = DependencyProperty.RegisterAttached("DialogResult", typeof(Boolean?), typeof(CloseDialog), new PropertyMetadata(DialogResultChanged)); private static void DialogResultChanged(DependencyObject pDependencyObject, DependencyPropertyChangedEventArgs e) { var wndWindow = pDependencyObject as Window; Boolean? blnIsModal = System.Windows.Interop.ComponentDispatcher.IsThreadModal; if (wndWindow != null) if (blnIsModal) wndWindow.DialogResult = e.NewValue as Boolean?; else wndWindow.Close(); } public static void SetDialogResult(Window pTarget, Boolean? pblnDialogResult) { pTarget.SetValue(DialogResultProperty, pblnDialogResult); } }
List 2
Here you can see in the List 2 that in the property metatdata that I have checked for the modal dialog and if the window is opened using ShowDialog then this flag will be true and the dialog is closed using the DialogResult else if the window is opened using the show function then window will be closed. So in this case you can use one property to handler both the dialog and window close. As in case of ShowDialog function we can check for the return value of the dialog to take further action if the result from the modal dialog is true.You can download the source code from here. 

The above idea of closing the dialog is taken from the following link.

All and any comments / bugs / suggestions are welcomed!

3 comments:

Anonymous said...

I seem to keep getting the following error at runtime:

{System.Windows.Markup.XamlParseException: Set property 'TestProject.Client.ViewModels.Helpers.CloseDialog.' threw an exception. [Line: 17 Position: 35] ---> System.ArgumentException: Object of type 'System.Windows.Data.Binding' cannot be converted to type 'System.Nullable`1[System.Boolean]'.
at System.RuntimeType.TryChangeType(Object value, Binder binder, CultureInfo culture, Boolean needsSpecialCast)
at System.RuntimeType.CheckValue(Object value, Binder binder, CultureInfo culture, BindingFlags invokeAttr)
at System.Reflection.MethodBase.CheckArguments(Object[] parameters, Binder binder, BindingFlags invokeAttr, CultureInfo culture, Signature sig)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at MS.Internal.XamlMemberInfo.SetValue(Object target, Object value)
at MS.Internal.XamlManagedRuntimeRPInvokes.SetValue(XamlTypeToken inType, XamlQualifiedObject& inObj, XamlPropertyToken inProperty, XamlQualifiedObject& inValue)
--- End of inner exception stack trace ---
at System.Windows.Application.LoadComponent(Object component, Uri resourceLocator)
at TestProject.Client.Views.Authentication.Login.InitializeComponent()
at TestProject.Client.Views.Authentication.Login..ctor()}

Anonymous said...

excellent!

Anonymous said...

you stole this from:
http://blog.excastle.com/2010/07/25/mvvm-and-dialogresult-with-no-code-behind/