データバインディングの話(UWP/C#)

 UWPにてUIのデータバインディングをしたい場合の話です。公式ページに超詳しく載っている内容を超ざっくりまとめます。

公式:データバインディングの概要:https://docs.microsoft.com/ja-jp/windows/uwp/data-binding/data-binding-quickstart

公式: データバインディングの詳細: https://docs.microsoft.com/ja-jp/windows/uwp/data-binding/data-binding-in-depth

xaml内での記述方法

 書き方は2パターンあります。「Binding ~」と「x:Bind ~」です。後者が新しい書き方で、より効率的に動作するそうです。
 ということで基本的には「x:Bind」を使えば良いのですが、これは新しい書き方だということで、ごくまれに上手く動かないパターンもあるというウワサです。私はそういう問題に当たったことはないですが、もし上手く動作せずに原因不明な時は「Binding」の書き方も試してみましょう。
 本記事では「x:Bind」の書き方だけ扱います。

 以下のコードは、baseSettingというデータクラスインスタンスのWidthの値に応じてGridの幅を変えたい、という時の例です。

<-- xamlの記述例 -->    
<Grid Width="{x:Bind baseSetting.Width}" />

 ここにもう1つ設定を追加できます。それはバインドの回数と方向に関する設定です。3パターンあります。「a.このバインドは1回限りでいい(デフォルト)」「b.アプリの実行中に値が何度も変更されるかもしれず、その都度コントロールに反映させたい」「c.コントロールが値を受け取るだけではなく、コントロールから変数に値を設定することもある」
 3パターンの書き方は次の通りです。

<!-- a -->
<Grid  Width="{x:Bind baseSetting.Width}" x:DefaultBindMode="OneTime"/>

<!-- b -->
<Grid  Width="{x:Bind baseSetting.Width}" x:DefaultBindMode="OneWay"/>

<!-- c -->
<Grid  Width="{x:Bind baseSetting.Width}" x:DefaultBindMode="TwoWay"/>

 OneTimeはデフォルト値なので、省略できます。
 OneWayとTwoWayは、「値が変わったら」というのを検出する必要がありますので、データクラス側に特別な設定が必要です。

データクラスの設定

 OneWayとTwoWayを使いたい場合は、データクラス側で値の変更通知を出せるようにします。具体的には、データクラスに「INotifyPropertyChanged」を実装します。実装しないとバインドが効きません。
 以下は、Widthだけ持ってるデータクラス:BaseSettingに「INotifyPropertyChanged」を実装した例です。クラス名の書き方とコンストラクタ以降に注目です。

public class BaseSetting : INotifyPropertyChanged
    {
        private double _Width;

        public double Width {
            get { return _Width; }
            set
            {
                _Width = value;
                RaisePropertyChanged("Width");
            }
        }

        // コンストラクタ
        public BaseSetting()
        {
            Width = 200;
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected void RaisePropertyChanged(string name)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(name));
            }
        }
    }

 これでOneWay/TwoWayバインドが効くようになります。

例外対策

 プロパティへのアクセスが何回も発生して、かつデータ型がstringだったりするとスタックオーバーフローが出るかもしれません。RaisePropertyChangedの呼び出しの前に、value反映前の値と比較(_StrXXX.Equals(value)など)して、値が変更されている時だけRaisePropertyChangedを呼び出すようにしてみてください。

溟犬一六(Ichiro Meiken)
  • 溟犬一六(Ichiro Meiken)
  • フリーランスのWEBクリエイター。小説、ゲーム、アプリなど幅広く活動中。
    Twitter : @dawn_gabacho

1件のピンバック

コメントは現在停止中です。