BETA

Windows Form(C#)で双方向バインド

投稿日:2019-11-06
最終更新:2019-11-06

WPFやXamarinのアプリではMVVMで作るのが一般的ですが、Windows Formでも双方向のバインドが使用できるのでメモとして残します。

デザイナ

  • デザイナでテキストボックス、DataGridView、ボタンを適当に配置します。
    よくある入力エリアと一覧です。

コード

入力エリア

  • 変更通知ができるよう、INotifyPropertyChangedの実装としてBindableBaseクラスを作成します
  • BindableBaseを継承したMyConditionクラスを作成します
    SetterでSetPropertyを呼び出すようにします
  • 各テキストボックスのTextプロパティにバインドする設定をします

一覧

  • 変更通知可能なBindingListを使用します
  • DataGridViewのDataSourceにBindingListを設定します
using System;  
using System.ComponentModel;  
using System.Runtime.CompilerServices;  
using System.Windows.Forms;  

namespace Practice-WinformDataBind01  
{  
    public partial class Form1 : Form  
    {  
        private BindingList<Book> _bindingBookList;  
        private MyCondition _condition;  

        public Form1()  
        {  
            InitializeComponent();  
        }  

        private void Form1_Load(object sender, EventArgs e)  
        {  

            //一覧部のバインディング  
            _bindingBookList = new BindingList<Book>()  
            {  
                new Book(id:"A",name:"書籍1"),  
                new Book(id:"B",name:"小説1")  
            };  

            this.dgv.DataSource = _bindingBookList;  

            //条件部のバインディング  
            _condition = new MyCondition();  
            this.txtId.DataBindings.Add(new Binding(nameof(this.txtId.Text), _condition, nameof(_condition.Id)));  
            this.txtName.DataBindings.Add(new Binding(nameof(this.txtId.Text), _condition,  nameof(_condition.Name)));  

        }  

        private void btnCheck_Click(object sender, EventArgs e)  
        {  
            if (_condition.Id == "A" && _condition.Name == "書籍1")  
            {  
                MessageBox.Show("存在する!");  
            }else  
            {  
                _condition.Id = "Z";  
                _condition.Name = "テスト";  
            }  
        }  

        private void btnAdd_Click(object sender, EventArgs e)  
        {  
            _bindingBookList.Add(new Book("X", "書籍2"));  
        }  
    }  

    class Book  
    {  
        public string Id { get; set; }  
        public string Name { get; set; }  

        public Book(string id,string name)  
        {  
            this.Id = id;  
            this.Name = name;  
        }  
    }  

    class MyCondition:BindableBase  
    {  
        private string id;  
        public string Id  
        {  
            get { return id; }  
            set { this.SetProperty(ref this.id, value); }  
        }  

        private string name;  
        public string Name  
        {  
            get { return name; }  
            set { this.SetProperty(ref this.name, value); }  
        }  

    }  

    public class BindableBase : INotifyPropertyChanged  
    {  
        public event PropertyChangedEventHandler PropertyChanged;  
        protected virtual bool SetProperty<T>(ref T field, T value, [CallerMemberName]string propertyName = null)  
        {  
            if (Equals(field, value)) { return false; }  
            field = value;  
            var h = this.PropertyChanged;  
            if (h != null) { h(this, new PropertyChangedEventArgs(propertyName)); }  
            return true;  
        }  
    }  
}  
  • Form Loadでバインディングの設定をしているため、各ボタンの処理ではUI(テキストボックス)でなく、バインドされたオブジェクトに対して参照や設定が行えます
  • プレーンなオブジェクトで扱えるようになるため、ロジックの分離やテスト容易性に繋がります。
  • 自前の実装でなく、PrismやReactive Propertyといったライブラリの利用も選択肢としてあります
技術ブログをはじめよう Qrunch(クランチ)は、プログラマの技術アプトプットに特化したブログサービスです
駆け出しエンジニアからエキスパートまで全ての方々のアウトプットを歓迎しております!
or 外部アカウントで 登録 / ログイン する
クランチについてもっと詳しく

この記事が掲載されているブログ

@yayaの技術ブログ

よく一緒に読まれる記事

0件のコメント

ブログ開設 or ログイン してコメントを送ってみよう