コントロールとデータを紐づけることをデータバインドといいます。
データバインドすることで、コントロール上の値を変更すればデータも自動で変更されるようになります。また、データを変更すればコントロール上の値も自動で変更されるようになります。
データバインドにより、自動的に変更されるようになるので、コード量を減らすことができます。
View-ViewModel-Modelの構成とし、バインド対象のデータをViewModelに配置しています。
Model
データに対応するModelクラスを作成します。
public class Item
{
public bool Done { get; set; }
public string Name { get; set; }
public string Detail { get; set; }
}
View
ViewModelのインスタンスを作成し、「View上のコントロール」と「ViewModelのデータプロパティ」をバインドします。
View: コントロール | ViewModel: データ |
---|---|
nameTextBox | _viewModel.Name |
detailRichTextBox | _viewModel.Detail |
todoGridView | _viewModel.Items |
データバインドすることで、各コントロールの値はViewModelのデータに自動的に反映されるので、addButton_Clickでコントローラの値をデータに格納するコードが不要になります。
public partial class MainView : Form
{
private MainViewModel _viewModel = new MainViewModel();
public MainView()
{
InitializeComponent();
nameTextBox.DataBindings.Add(nameof(nameTextBox.Text), _viewModel, nameof(_viewModel.Name));
detailRichTextBox.DataBindings.Add(nameof(detailRichTextBox.Text), _viewModel, nameof(_viewModel.Detail));
todoGridView.DataBindings.Add(nameof(todoGridView.DataSource), _viewModel, nameof(_viewModel.Items));
}
private void addButton_Click(object sender, EventArgs e)
{
_viewModel.Items.Add(new Item { Name = _viewModel.Name, Detail = _viewModel.Detail });
}
}
ViewModel
バインド対象のデータをViewModel上に配置します。このデータをViewから呼び出します。
NameとDetailプロパティに関しては、コードでの変更を画面に反映させるために、PropertyChangedイベントを発生させる必要があります。こうすることで、UI→データ、データ→UIの双方向のデータバインドとなります。
public class MainViewModel : INotifyPropertyChanged
{
private string _name = string.Empty;
private string _detail = string.Empty;
public event PropertyChangedEventHandler PropertyChanged;
public string Name
{
get { return _name; }
set
{
if (_name == value) return;
_name = value;
if(PropertyChanged != null)
{
// コードでの変更を画面に反映させるために必要(データ→UI)
PropertyChanged(this, new PropertyChangedEventArgs(nameof(Name)));
}
}
}
public string Detail
{
get { return _detail; }
set
{
if (_detail == value) return;
_detail = value;
if (PropertyChanged != null)
{
// コードでの変更を画面に反映させるために必要(データ→UI)
PropertyChanged(this, new PropertyChangedEventArgs(nameof(Detail)));
}
}
}
public BindingList<Item> Items { get; set; } = new BindingList<Item>();
}
コメント