Basic Human Being
Basic Human Being

Reputation: 93

Novice MVVM in C# trying to close application with Esc (handling key commands)

I'm learning/practicing basic MVVM framework solutions in C#

I have a small program that plays around with a ComboBox, if user select something from box, it is displayed in a MsgBox. Now I want it to close on esc key. I found a lot of solved questions here about that like these:

Keyboard events in a WPF MVVM application? Press Escape key to call method

But I'm unable to implement any of these... I dont even seems to be able to set KeyPreview to True (Im okey to just write in to the Form now, but the funny thing is, I can't make it work.)

My problems are, I did not use c# for a while, Im not sure what to use exactly (KeyEventArg KeyEventHandler, should I use e.Key, e.keyDown?) and Im not sure where to put this code. I read a few things about how to handel it in the XAML file, which would be the best but was unable to do it. Right now here is my code in the App.xaml.cs, I tried to implement it in various places but I reather ask when Im coding and dont know what to do/what Mi doing exactly, so here Im.

My code right now:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;

namespace WpfComboBoxStrinbgListMVVM
{



    public class MainViewModel
    {

        public MainViewModel()
        {
            ItemList = new List<string> { "item1", "item2", "item3" };
        }
        public List<string> ItemList { get; set; }

        private string seletedElement;
        public string SelectedElement
        {
            get { return seletedElement; }
            set
            {
                seletedElement = value;
                MessageBox.Show(seletedElement);
            }
        }

        private void EscKeyDown(object sender, KeyEventArgs e)
        {

            if (e.Key == Key.Escape)
            {
                MessageBox.Show("Escape key pressed");
                // mainWindow.Close();? MainWievModel.Close(); App.Close();

            }

        }

        //private void Form1_KeyDown(object sender, KeyEventArgs e)
        //{
        //    if (e.KeyCode == Keys.Escape)
        //    {
        //        MessageBox.Show("Escape key pressed");

        //        // prevent child controls from handling this event as well
        //        e.SuppressKeyPress = true;
        //    }
        //}

    }

}

Upvotes: 1

Views: 1157

Answers (2)

MikeT
MikeT

Reputation: 5500

the simplest method in this case would be to use the predefined ApplicationCommands.Close command

this would look like this

<Window.InputBindings>
    <KeyBinding Key="Esc" Command="ApplicationCommands.Close" />
</Window.InputBindings>

then in the codebehind

this.CommandBindings.Add(
  new CommandBinding(
    ApplicationCommands.Close,
    (s,a)=>Application.Current.Shutdown() //or this.Close() depending on what you want to close
  )
);

other options would include implementing a custom class that uses the ICommand interface or using one of the hundreds of libraries that provide this functionality such as prism's Delegate Command or the Relay command

EDIT

as you are not familiar with anonymous delegates the code behind could also be written like this

this.CommandBindings.Add(
  new CommandBinding(
    ApplicationCommands.Close,
    PerformClose
  )
);

public void PerformClose(object sender, ExecutedRoutedEventArgs args)
{
    Application.Current.Shutdown();
}

Upvotes: 2

Jake
Jake

Reputation: 28

You can use KeyBinding,sample code like below:

<InputBindings>
   <KeyBinding Key="Esc" Command="{Binding CloseCommand}"/>
</InputBindings>

In window.xaml(I'm afraid you have to write a little code behind :( )

Window(){
  InitializeComponent();
  this.DataContextChanged += (sender,e){
    var vm = e.NewValue as WindowViewModel;
    if(vm != null){
       vm.CloseFunc = () => this.Close();
    }
 }

}

For WindowViewModel: public Action CloseFunc{get;set;}

private RelayCommand _closeCommand;
public RelayCommand CloseCommand =>
     _closeCommand??(_closeCommand = 
    new RelayCommand(() =>{
       CloseFunc?.Close();
   })));

Upvotes: 1

Related Questions