WPFコントロール:TextBox(文字入力:1行・複数行)

テキストボックス コンピュータ
テキストボックス

テキストボックスで文字を入力すると、

デバックコンソールに入力した文字列が表示されます。

同じ動作のサンプルコードを、

  1. コードビハインド
  2. データバインディング(INotifyPropertyChanged)
  3. データバインディング(ReactiveProperty)

の3種類で作成してみました。

コードビハインド

XAML

<TextBox Width="200"
    TextChanged="TextBox_TextChanged"/>

コードビハインド

private void TextBox_TextChanged(object? sender, TextChangedEventArgs e)
{
    var tb = sender as TextBox;
    Debug.Print(tb?.Text);
}

XAMLのTextChangedイベントで呼び出されるメソッドTextBox_TextChanged()を指定しています。

メソッドの引数は、イベント元のオブジェクトsenderと、イベント情報が含まれるeが渡されます。

senderはobject型なので、TextBoxにキャストしています。

データバインディング(INotifyPropertyChanged)

XAML

<TextBox Width="200"
            Text="{Binding Text,
                UpdateSourceTrigger=PropertyChanged}" />

UpdateSourceTrigger=PropertyChangedは1文字入力ごとにイベント発生。
デフォルトはフォーカス喪失ですが、このサンプルだとコントロールがTextBoxだけなので、イベントが発生しない為。

ViewModel

using System.Diagnostics;
using Maywork.WPF.Helpers;

namespace WpfSample01;
public class MainWindowViewModel : ViewModelBase
{
    private string _text = "";

    public string Text
    {
        get => _text;
        set
        {
            if (_text == value) return;
            _text = value;

            OnPropertyChanged();

            Debug.Print(_text);
        }
    }
}

ViewModelBase.cs

Text プロパティはデータバインディングの対象として使用されています。

ViewModel の Text プロパティでは、set アクセサー内で
OnPropertyChanged() を呼び出すことで変更通知を行います。

これによりプロパティの変更が UI に通知され、
TextBox の表示内容が更新されます。

他にも通知を行いたい処理がある場合は、setter 内に処理を追加する形になります。
ただし、setter 内で実行される処理であるため、
重たい処理にならないよう注意しましょう。

データバインディング(ReactiveProperty)

XAML

<TextBox Width="200"
            Text="{Binding Text.Value,
                UpdateSourceTrigger=PropertyChanged}" />

ViewModel

using System.Diagnostics;
using Maywork.WPF.Helpers;
using Reactive.Bindings;
using Reactive.Bindings.Extensions;

namespace WpfSample01;
public class MainWindowViewModel : ViewModelBaseRx
{
    public ReactivePropertySlim<string> Text {get; set;}
        = new("");
    
    // コンストラクタ
    public MainWindowViewModel()
    {
        Text
            .Subscribe(value => Debug.Print($"{value}"))
            .AddTo(Disposable);
    }
}

ViewModelBaseRx.cs

XAML 上では Text.Value をバインディング名として使用し、
ViewModel の ReactivePropertySlim<string> Text とバインドしています。

Text の値が変更されると .Subscribe() 内の処理が実行されます。

.AddTo(Disposable) は Text を自動的に Dispose() するための
仕組みに登録する拡張メソッドです。

INotifyPropertyChanged 版では、プロパティのボイラープレート
(フィールド定義、Getter、Setter)が必要になりますが、
ReactiveProperty を使用するとシンプルで洗練された形で記述できます。

複行入力等

オプション例:改行可・タブ入力可・行末折り返し・縦スクロールバー自動・高さ指定(120)

<TextBox AcceptsReturn="True"
         AcceptsTab="True"
         TextWrapping="Wrap"
         VerticalScrollBarVisibility="Auto"
         Height="120"/>

オプション例:改行可・タブ入力可・行末折り返し無し・横スクロールバー自動・縦スクロールバー自動

<TextBox AcceptsReturn="True"
         AcceptsTab="True"
         TextWrapping="NoWrap"
         HorizontalScrollBarVisibility="Auto"
         VerticalScrollBarVisibility="Auto"/>

コメント