locked
Close a dialog on button click in MVVM RRS feed

  • Question

  • Hello,

    In my application, I have a Window which is used for selecting some files and reading the files. This class is binded with a ViewModel class which is having a command (ReadFilesCommand) to read the files.

    When I complete the file reading operation successfully, I want to close the dialog automatically. If its not completed successfully then a dialog should get pop up.

    How I can do this in the ViewModel class and without writing any code in WindowXAML.cs file?

    Thanks,

    IamHuM

    Friday, May 15, 2015 4:23 AM

Answers

All replies

  • Step 1 : Add reference to System.Windows.Interactivity & Include below line in your window 

    xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"

    Step 2 : Add the following EventTrigger to your button

    <Button x:Name="Click">
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="Click">
                    <i:InvokeCommandAction Command="{Binding ReadFilesCommand}" CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}" />
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </Button>

    Step 3 : Add the following to your window (for keyboard handling only - Add if needed)

    <Window.InputBindings>
            <KeyBinding Key="Enter" Command="{Binding ReadFilesCommand}" CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}" />
        </Window.InputBindings>

    Step 4: command execute and canexecute methods would be as below

    public bool CanExecute(object parameter) { return (parameter is Window); } /// <summary> /// /// </summary> /// <param name="parameter"></param> public void Execute(object parameter) { if (this.CanExecute(parameter)) {

    //ReadFilesHere

    //If Successful ((Window)parameter).Close();

    //Else

    //Show MessageBox with errors } }


    Happy Coding :),

    Kashish.

    • Proposed as answer by KashishArora Friday, May 15, 2015 6:17 AM
    Friday, May 15, 2015 6:16 AM
  • In this instance I would prefer a little code code behind to the alternative.

    Just doing this.close() in a public action/method.

    http://jkshay.com/closing-a-wpf-window-using-mvvm-and-minimal-code-behind/

    Or using mvvm light to decouple them and send a close message.

    http://social.technet.microsoft.com/wiki/contents/articles/26070.aspx

    The cleanest no code behind option (IMO)  involves an attached property.  These things are dependency properties so you can bind them and they have a reference to the thing they are attached to so you can call .Close() on it.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows;
    
    namespace wpf9
    {
        public class WindowExtender : DependencyObject
        {
            public static readonly DependencyProperty CloseProperty =
                DependencyProperty.RegisterAttached("Close", typeof(bool?), typeof(WindowExtender),
                new PropertyMetadata(default(bool?), OnCloseChanged));
    
            public bool? Close
            {
                get { return (bool?)GetValue(CloseProperty); }
                set { SetValue(CloseProperty, value); }
            }
    
            private static void OnCloseChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
            {
                Window win = obj as Window;
                if (win == null)
                    return;
                if((bool)e.NewValue)
                    win.Close();
            }
    
        }
    }

    You make it close by binding a property in your viewmodel to that and just setting it to true.

    <Window x:Class="wpf9.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
           Height="350" Width="525"
            xmlns:local="clr-namespace:wpf9"
            SizeToContent="WidthAndHeight"
            
            >
        <Window.Resources>
            <local:WindowExtender x:Key="CloseWindow" Close="{Binding CloseWindow}"/>

    Here CloseWindow would be that bool property in your viewmodel.

    .


    Hope that helps.

    Technet articles: Uneventful MVVM; All my Technet Articles

    Friday, May 15, 2015 8:04 AM
  • You could display the window using an interaction request that is being raised by the view model and then call the Show() method in a custom TriggerAction. Please refer to my blog post below for more information and a complete code sample.

    Implement a confirmation dialog in WPF using MVVM and Prism: http://blog.magnusmontin.net/2013/04/20/implement-a-confirmation-dialog-in-wpf-with-mvvm-and-prism/

    The other option is to send a message from the view model to the view using an event aggregator or a messenger and then simply close the window by calling the Close() method on the receiving side, i.e. in the view itself. Please refer to another blog post of mine for more information about how you could raise an event using the EventAggregator class in Prism: http://blog.magnusmontin.net/2014/02/28/using-the-event-aggregator-pattern-to-communicate-between-view-models/

    Hope that helps.

    Please remember to close your threads by marking helpful posts as answer and then start a new thread if you have a new question. Please don't ask several questions in the same thread.

    • Proposed as answer by Xavier Xie-MSFT Friday, May 22, 2015 8:04 AM
    • Marked as answer by Barry Wang Tuesday, May 26, 2015 2:59 AM
    Friday, May 15, 2015 1:20 PM