Green Falcon
Green Falcon

Reputation: 836

Implementing a custom WPF Command

I wanted to implement a custom WPF command and I searched and found the following code:

public static class CustomCommands
{
    public static readonly RoutedUICommand Exit = new RoutedUICommand
    (
        "Exit",
        "Exit",
        typeof(CustomCommands),
        new InputGestureCollection()
        {
            new KeyGesture(Key.F4, ModifierKeys.Alt)
        }
    );

    //Define more commands here, just like the one above
}


There are two things that I can't figure out.

  1. Is it necessary to have commands static readonly? Cant we just declare it using const?

  2. What exactly new InputGestureCollection() { new KeyGesture(Key.F4, ModifierKeys.Alt) } is? If it is calling default constructor and initializing properties so there should be a property to be assigned to, but there is nothing to be assigned. InputGestureCollection has braces, but inside braces it is not initialing any properties. How? What is this type of statement?

Upvotes: 3

Views: 4009

Answers (2)

Dominik
Dominik

Reputation: 1741

First of all, you need to get some basic understanding of WPF with MVVM. You have a class that you are going to bind to your UI. That class is not the .xaml.cs

It is completely independent of the View. You need to put an instance of the class into the DataContext of the Window you can do this in the .xaml.cs by calling sth like that:

this.DataContext = new MyViewModel();

Now your class MyViewModel needs a Property of type ICommand. Best practice is to make a class that implements ICommand. Normally you call it DelegateCommand or RelayCommand. Example:

public class DelegateCommand : ICommand
{
    private readonly Predicate<object> _canExecute;
    private readonly Action<object> _execute;

    public event EventHandler CanExecuteChanged;

    public DelegateCommand(Action<object> execute)
        : this(execute, null)
    {
    }

    public DelegateCommand(Action<object> execute,
                   Predicate<object> canExecute)
    {
        _execute = execute;
        _canExecute = canExecute;
    }

    public bool CanExecute(object parameter)
    {
        if (_canExecute == null)
        {
            return true;
        }

        return _canExecute(parameter);
    }

    public void Execute(object parameter)
    {
        _execute(parameter);
    }

    public void RaiseCanExecuteChanged()
    {
        if (CanExecuteChanged != null)
        {
            CanExecuteChanged(this, EventArgs.Empty);
        }
    }
}

Then in your ViewModel you create a property with an Instance of that class in it. Like that:

public class MyViewModel{

   public DelegateCommand AddFolderCommand { get; set; }
   public MyViewModel(ExplorerViewModel explorer)
   {           
       AddFolderCommand = new DelegateCommand(ExecuteAddFolderCommand, (x) => true);
   }

   public void ExecuteAddFolderCommand(object param)
   {          
       MessageBox.Show("this will be executed on button click later");
   }
}

In your view you can now bind the command of a button to that property.

<Button Content="MyTestButton" Command="{Binding AddFolderCommand}" />

A routed command is something that already exists in the framework by default (copy, paste etc). If you're a beginner to MVVM you shouldn't be thinking of creating routed commands before you get the basic understanding of "normal" commands.

To answer your first question: It is absolutely not nessesary to make Commands static and/or const. (See class MyViewModel)

Your 2nd question: You can initialize Lists with default values that you put into the {-brackets. Example:

var Foo = new List<string>(){ "Asdf", "Asdf2"};

You don't have a object you initialize properties of. You have a list you initialize and then the Add() is called with the parameters you put in the {-brackets.

That's what basicly happens in your case too. You have a collection that you initialize with some values.

Upvotes: 8

ChrisF
ChrisF

Reputation: 137108

To answer your second question:

new InputGestureCollection()
{
    new KeyGesture(Key.F4, ModifierKeys.Alt)
}

This is an example of a collection initializer and is equivalent to:

var collection = new InputGestureCollection();
collection.Add(new KeyGesture(Key.F4, ModifierKeys.Alt));

It's just a shorthand, and something that ReSharper suggests.

Upvotes: 1

Related Questions