C#
WPF
Xaml
MVVM

MVVMでCommandBindingsを使う

やりたいこと

コードビハインドを使わず、ApplicationCommands等の定義済みコマンドにViewModelのコマンドをバインドできるようにする。

実装

ViewModelのコマンドと定義済みコマンドを関連づけるビヘイビアを作成する。

ビヘイビア
using System.Windows;
using System.Windows.Documents;
using System.Windows.Input;

namespace Sample {
    //コマンドごとに添付プロパティを実装する
    //以下はApplicationCommands.Newにバインドする例
    public static class AttachedCommandBindings {
        public static DependencyProperty NewCommandProperty
            = DependencyProperty.RegisterAttached(
                "NewCommand",
                typeof(ICommand),
                typeof(AttachedCommandBindings),
                new PropertyMetadata(null, OnNewCommandChanged)
            );

        public static void SetNewCommand(UIElement element, ICommand value)
            => element.SetValue(NewCommandProperty, value);

        public static ICommand GetNewCommand(UIElement element)
            => (ICommand)element.GetValue(NewCommandProperty);

        private static void OnNewCommandChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) {
            UIElement element = sender as UIElement;
            if (element == null)
                return;

            ICommand command = e.NewValue as ICommand;
            if (command == null)
                return;

            RegisterCommandBinding(element, ApplicationCommands.New, command);
        }

        private static void RegisterCommandBinding(UIElement element, RoutedUICommand routedCommand, ICommand command) {
            var binding = new CommandBinding(
                routedCommand,
                (sender1, e1) => command.Execute(null),
                (sender1, e1) => e1.CanExecute = command.CanExecute(null)
            );

            CommandManager.RegisterClassCommandBinding(element.GetType(), binding);

            element.CommandBindings.Add(binding);
        }
    }
}

使い方

XAML
<Window x:Class="Sample.MainView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:Sample"
        Title="MainView" Height="300" Width="300"
        local:AttachedCommandBindings.NewCommand="{Binding NewCommand}">
    <Grid>
        <TextBox />
    </Grid>
</Window>