【WPF(XAML)C#2】Label/TextBlock/TextBoxの違い

Label と TextBlockの違いって?

それではセクション2は予告通り、Viewからの値の反映をやろうと思いますがその前に文字つながりでTextBlockとLabelについて触れたいと思います。

TextBlockとLabelもどちらも文字を入れるのに使用します。単純に文字を書くだけならどっちを使ってもあまり変わりませんが、TextBlockとLabelも一応違いはあります。こちらも概念的なものは興味があれば検索してみてください。

イナコーシステムが実務で関係すると思う決定的な違いはLabelはTemplateが使用できることです。TextBlockはStyleは使用できますがTemplateは使えないので文字を装飾することはできません

Templateとは?

Templateとはひな形を作成するようなもので種類も色々ありますが一番使われるのはDataTemplateだと思います。Templateを使用するとXAML上の記述も共通化できたりとかします。ではLabelTemplateを使用するとどういった表現ができるか見てみましょう。

LabelContentで文字を入力し、aaaaという名前で定義したTemplateをLabelが参照することによって右に映っている画面のようにContentで書かれた文字が赤い□で囲われています。

この赤い四角はTemplateの定義で作られていて他のLabelは同じTemplateを参照しているので同じデザインの装飾ができあがるわけです。TextBlockではTemplateを使用できませんので試しにTemplateにあったBorderによる線をTextBlockの周りに書いてみましたが、線が横いっぱいに広がってしまい、同じ結果にならない事がわかります。

実務ベースでのLabelとTextBlockの違い

Labelは上記のようなTemplateで文字自体に装飾が出来ますので、主にタイトルで使用する事をオススメします。TextBlockは使用数の多い内容を表示する時にオススメ

画像のだと、「天気」「気温」「降水確率」のような表題をLabelにして、「晴れ、26℃、10%」といった内容部分をTextBlockにすると明確に役割も分かれて構成もわかりやすいと思います。

TextBox

こちらはHTMLでもおなじみですが、ユーザによるテキスト入力エリアを作るためのものです。ただ、注意して頂きたいのがこれもTextBoxを作ってテキストを入力しただけではBindingされた値はViewModel側に反映されません。ViewModelからViewに通知するためにNotifyPropertyChangedを使ったように、View側からViewModelに変更を通知するには<TextBox Text=”{Binding testNo2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}/>と指定します。後半の二つはセットかつ固定なので気をつけてください。

ModeのTwoWayViewModelとModel双方向に通知可能にし、UpdateSourceTrigger(通知する契機)は値が元の値から変更されたら。ということを意味しています。本来のMVVMパターンではViewModel → Viewが正しいので何もしないとModeには片方向であるOneWayが指定されています。

ちなみにCS側のViewModelは前回、オススメに挙げたBindableBaseを使用したものに変更しました。

    public partial class MainWindow : Window
    {
        MainWindowViewModel MyVM = new MainWindowViewModel();

        public MainWindow()
        {
            InitializeComponent();

            // Model
            this.DataContext = MyVM;

            MyVM.testNo = 1111;
            MyVM.testNo2 = 3333;
        }
    }

    public class MainWindowViewModel : BindableBase
    {
        private int? _testNo;
        public int? testNo
        {
            get => _testNo;
            set => SetProperty(ref _testNo, value);
        }

        // int? でなくStringであることに意義がある。(""がint型にはないから)
        private string _testNo2;
        public string testNo2
        {
            get => _testNo2;
            set => SetProperty(ref _testNo2, value);
        }
    }

それでは以下の実際操作した動画をご覧ください。通常Model側が上のマークされている3333を設定したらtestNo2のsetが動作しますが、この部分がView側を入力しても止まるようになっています。

この時点でViewModelのtestNo2は更新され、同時にNotifyPropertyChangedを行いますので画面側にもtestNo2が更新された事を通知します。今までの説明だと通知されたら画面上の値も変わると説明しました。この方法を使うとModel側以外でも画面の値を変更することができます。その動画がこちら。

動画を見てもらえばわかりますがTextBoxに入力された値で右上の値も変わっているのがおわかりになると思います。これがNotifyPropertyChangedとTwoWayの組み合わせの大事なポイントですので抑えておきましょう。

今回は値が反映される例として紹介しましたが実務は上記のような使い方はせず、業務画面の環境設定でTextBoxによる入力で値を変更したものを確定したらModel側でAPIにアクセスし、DBに保存するといった使い方が主流だと思います。

型に気をつけよう

ちなみに型にも気をつけてください。TextBoxは基本「文字列型」なのでtestNoと同じようにintを使っているとTextBoxの入力情報を消しても空にはできません。

以下の動画をご覧ください。

この動画はtestNo2をint?型で定義した時の結果ですが、右上が全て削除されていないのがおわかりになるでしょうか?これは本来TextBoxを全部削除した時は“”(空文字)をViewModelに投げたいのですが、ViewModel側はint型のため、””の文字を受け取れず、更新できない(画面に通知できない)のです。

そもそもTextBlock/TextBoxは本来、文字列を表示するものなのでTextBlockにBindingする文字は基本stringに統一しておくと間違いも起こりにくいでしょう。

このセクションのまとめ

  • LabelはTemplateが使えるのでタイトルのような装飾に使用
  • TextBlockは内容を中心に使用
  • TextBoxはMode=TwoWay, UpdateSourceTrigger=PropertyChangedをセットにして使用する。(双方向設定)
  • テキスト関係のものをBindingする時はstring型で統一すると間違いが起こらない

次回はDockPanel/StackPanelの利用用途について説明したいと思います。それでは~