最近あまり面白い話題が少ない感じでしたがついに来ました。みんな大好き Windows フォームアプリのお話です。
↑ のブログ記事。見ていきましょう!
※ 現在 WPF でなく WinForms を愛用している日本の IT 技術者が WinForms アプリを MVVM で作りたいと思っているかは別として。
■ CommandParameter プロパティ
ButtonBase クラスと ToolStripItem クラスに CommandParameter プロパティが追加されたとのことです。
ButtonBase クラス、確かに、バージョン 7 からとなっています。
learn.microsoft.com
ToolStrigItem クラスには見当たりません......。
learn.microsoft.com
しかし Visual Studio で見ると確かにいますね。
試してみましょう。
■ 検証コード
public class BindableBase : System.ComponentModel.INotifyPropertyChanged { public event System.ComponentModel.PropertyChangedEventHandler? PropertyChanged; protected bool SetProperty<T>(ref T property, T value, [System.Runtime.CompilerServices.CallerMemberName] string propertyName = "") { if (Object.Equals(property, value)) return false; property = value; PropertyChanged?.Invoke(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); return true; } } class Command : System.Windows.Input.ICommand { public event EventHandler? CanExecuteChanged; private readonly Action<object?> _commandAction; private readonly Func<bool>? _canExecuteCommandAction; public Command(Action<object?> commandAction, Func<bool>? canExecuteCommandAction = null) { _commandAction = commandAction; _canExecuteCommandAction = canExecuteCommandAction; } public bool CanExecute(object? parameter) => _canExecuteCommandAction?.Invoke() ?? true; public void Execute(object? parameter) => _commandAction.Invoke(parameter); public void NotifyCanExecuteChanged() => CanExecuteChanged?.Invoke(this, EventArgs.Empty); } public class ViewModel : BindableBase { bool _enabled = true; private string _text; public string Text { get => _text; private set => SetProperty(ref _text, value); } public System.Windows.Input.ICommand ButtonCommand { get; init; } public ViewModel() { ButtonCommand = new Command(((parameter) => Text += $"Button clicked: {parameter?.ToString()}\n"), canExecute); bool canExecute() => _enabled; } }
using System.Windows.Forms; namespace WinFormsApp1 { public partial class Form1 : Form { public Form1() { this.components = new System.ComponentModel.Container(); InitializeComponent(); var viewModel = new ViewModel(); var bindingSource = new System.Windows.Forms.BindingSource(components); bindingSource.DataSource = viewModel; var button = new System.Windows.Forms.Button { AutoSize = true, Location = new System.Drawing.Point(16, 32), Size = new System.Drawing.Size(94, 29), Text = "button1", UseVisualStyleBackColor = true, }; var bitmap = new System.Drawing.Bitmap(24, 24); System.Drawing.Graphics.FromImage(bitmap).FillRectangle(System.Drawing.Brushes.Aqua, new System.Drawing.Rectangle(0, 0, 24, 24)); var toolStripButton = new System.Windows.Forms.ToolStripButton { Image = bitmap, Size = new System.Drawing.Size(29, 24), }; var toolStrip = new System.Windows.Forms.ToolStrip { ImageScalingSize = new System.Drawing.Size(20, 20), Location = new System.Drawing.Point(0, 0), Size = new System.Drawing.Size(800, 27) }; var label = new System.Windows.Forms.Label { AutoSize = true, Location = new System.Drawing.Point(20, 172), Size = new System.Drawing.Size(50, 20), Text = "label1", }; button.DataBindings.Add(new System.Windows.Forms.Binding("Command", bindingSource, "ButtonCommand", true)); toolStripButton.DataBindings.Add(new System.Windows.Forms.Binding("Command", bindingSource, "ButtonCommand", true)); label.DataBindings.Add(new System.Windows.Forms.Binding("Text", bindingSource, "Text", true)); button.CommandParameter = "saitama is best!"; toolStripButton.CommandParameter = "gunma is nice!"; this.Controls.Add(button); toolStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { toolStripButton }); this.Controls.Add(toolStrip); this.Controls.Add(label); } } }
実行結果
計算通り! 画面上部の普通のボタンとツールバーのボタン (aqua 色の四角) をクリックすると CommandParameter の内容を含んでテキストが更新されました。
■ コードの要点
フォームのコントロールを作っているところで普通に文字列を設定しています。Command の Execute の引数に確かに渡されています。
button.CommandParameter = "saitama is best!"; toolStripButton.CommandParameter = "gunma is nice!";
■ CommandParameter へのバインディング
CommandParameter へのバインディングもできます。
button.DataBindings.Add(new System.Windows.Forms.Binding("CommandParameter", bindingSource, "Text", true)); toolStripButton.DataBindings.Add(new System.Windows.Forms.Binding("CommandParameter", bindingSource, "Text", true));
ボタンを押すたびに CommandParameter の値が追記される ViewModel の Text プロパティをバインドしてみたので、ボタンを押すたびに加速しながら文字列が増えていくようになりました。
次回
次回は OnRequestCommandExecute メソッドを見ていきましょう。