WindowsフォームでのDataBinding
はじめに
長年Windowsフォームで実装してましたが、コードでのDataBindingを行ったことも、ButtonのクリックイベントをBindingする事もなかったので、今更ながら実装してみました。
環境
VS2022
Windwos11 Pro(64bit)
プロジェクトの作成
新しいプロジェクトの作成で、「Windowsフォームアプリ」を選択
作成したプロジェクトにViewModelクラスを追加
コードで実装してみる
namespace WinFormsApp1
{
internal class ViewModel : BindableBase
{
public string Text {
get => _text;
set => SetProperty(ref _text, value);
}
string _text = "";
public string Label { get => _label; set => SetProperty(ref _label, value); }
string _label = "";
public System.Windows.Input.ICommand ButtonCommand { get; init; }
public ViewModel() {
ButtonCommand = new Command(Apply);
}
void Apply()
{
if (int.TryParse(Text, out var num))
{
Label = $"{num}";
}
else
{
Label = "整数の数値を入力してください";
}
}
}
}
BindableBaseを使用したので、Nugetから「Prism.Core」を入れてください。
テキストボックスに入力した文字を、ボタンを押すことで、ラベルに反映する実装として、それらコントロールにBindするプロパティ達を実装します。
ボタンのクリックイベントをBindingするためにCommandクラスを実装します。プロジェクトに追加して、実装ください。
内容はほぼ定型文ですね。
namespace WinFormsApp1
{
internal class Command : System.Windows.Input.ICommand
{
public event EventHandler? CanExecuteChanged;
private readonly Action _commandAction;
private readonly Func<bool>? _canExecuteCommandAction;
public Command(Action commandAction, Func<bool>? canExecuteCommandAction = null)
{
_commandAction = commandAction;
_canExecuteCommandAction = canExecuteCommandAction;
}
public bool CanExecute(object? parameter) => _canExecuteCommandAction?.Invoke() ?? true;
public void Execute(object? parameter) => _commandAction.Invoke();
public void NotifyCanExecuteChanged() => CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}
}
これは、丸まるコピーで使いまわしです。
次に、Formのコンストラクタで、Bindingの設定を行います。
namespace WinFormsApp1
{
public partial class Form1 : Form
{
public Form1()
{
this.DataContext = new System.Windows.Forms.BindingSource(this.components = new System.ComponentModel.Container())
{
DataSource = new ViewModel()
};
InitializeComponent();
textBox1.DataBindings.Add(new System.Windows.Forms.Binding("Text", this.DataContext, "Text", true));
label1.DataBindings.Add(new System.Windows.Forms.Binding("Text", this.DataContext, "Label", true));
button1.DataBindings.Add(new System.Windows.Forms.Binding("Command", this.DataContext, "ButtonCommand",true));
}
}
}
別段難しいことはありません。3種のコントロール毎の設定を行っています。
Form1に配置するコントロールは以下の感じで置いてます。
デザイナ画面の設定で極力楽をする
Form1に配置するコントロールは、上記の通りで同じとしてください。
さすがにViewModelクラスは実装する必要があるので、クラスを追加して、コードを記述。なのでBindableBaseも使用するので、NegetからのPrism.Coreも必要です。
ボタン操作もあるので、Commandの実装も必要ですね。
ViewModel.csとCommand.csを追加してください。
それと、後でViewModelは外から見たいので、クラスをPublicとしておいて下さい。
namespace WinFormsApp2
{
- internal class ViewModel : BindableBase
+ public class ViewModel : BindableBase
{
public string Text
Formのプロパティから、「DataBindings」を選択して「DataContext」を選択して、下矢印をクリック、「オブジェクトデータソースを追加します」をクリック下さい。
ViewModelが選択できるので、選択してOKを押す
ViewModelが表示されててないなら、一回ビルドしてみて下さい。
あとは、コントロール毎に使用するプロパティを設定していく。
コントロール | プロパティ画面 | 選択項目 |
---|---|---|
txtBox1 | DataBindings/Text | Text |
label1 | DataBindings/Text | Label |
button1 | DataBindings/Command | ButtonCommand |
最後にForm1にちょっと、コードを追加
public Form1()
{
InitializeComponent();
+ viewModelBindingSource.DataSource = new ViewModel();
}
Discussion