数据绑定是一个很强大且优雅的技能,之前用过好多次,但有些地方总不是特别清晰,常常需要重新翻阅资料来回顾,于是这次用了几天时间好好梳理一下,记录一下。
首先数据绑定对数据对象的要求:需要是公有属性(不支持字段和私有属性)。
如果需要在数据内容发生变化时自动更新到控件,则需要实现INotifyPropertyChanged接口,其包含 PropertyChanged事件,在属性变化时引发PropertyChanged事件。
如果绑定对象为集合时,需要在集合内容发生变化时自动更新到控件,则需要INotifyCollectionChanged接口,其包含CollectionChanged事件,目前内置的泛型集合 ObservableCollection 实现了该接口。
通常在设置绑定时,我们需要指定数据上下文,DataContext,如果控件没有设置DataContext,则会去找父容器的DataContext,依层级依次查找。也有些控件直接在代码中指定ItemsSource的。如果要绑定的数据依赖于另外一个控件的值,可以在DataContext中,绑定到另外一个控件的选中项,然后设置该控件的数据源或者绑定值。
MainWindow.xaml
BindData:
BindDatas:
ExchangeID:
InstrumentID:
InstrumentName:
MainWindow.xaml.cs
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows;
namespace TestBinding;
public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler? PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
protected virtual bool SetProperty(ref T member, T value, [CallerMemberName] string? propertyName = null)
{
if (EqualityComparer.Default.Equals(member, value))
{
return false;
}
member = value;
OnPropertyChanged(propertyName);
return true;
}
}
public class ExchangeViewModel : ViewModelBase
{
private string exchangeID = string.Empty;
public string ExchangeID { get => exchangeID; set => SetProperty(ref exchangeID, value); }
public ObservableCollection Instruments { get; set; } = new ObservableCollection();
}
public class InstrumentViewModel : ViewModelBase
{
public InstrumentViewModel(string exchangeID, string instrumentID, string instrumentName)
{
ExchangeID = exchangeID;
InstrumentID = instrumentID;
InstrumentName = instrumentName;
}
private string _exchangeID = string.Empty;
private string _instrumentID = string.Empty;
private string _instrumentName = string.Empty;
public string ExchangeID { get => _exchangeID; set => SetProperty(ref _exchangeID, value); }
public string InstrumentID { get => _instrumentID; set => SetProperty(ref _instrumentID, value); }
public string InstrumentName { get => _instrumentName; set => SetProperty(ref _instrumentName, value); }
}
///
/// Interaction logic for MainWindow.xaml
///
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
parentContainer.DataContext = this;
Exchanges = new();
ExchangeViewModel exchange1 = new ExchangeViewModel();
exchange1.ExchangeID = "SHSE";
exchange1.Instruments.Add(new InstrumentViewModel("SHSE", "601155", "新城控股"));
exchange1.Instruments.Add(new InstrumentViewModel("SHSE", "600036", "招商银行"));
exchange1.Instruments.Add(new InstrumentViewModel("SHSE", "600266", "城建发展"));
exchange1.Instruments.Add(new InstrumentViewModel("SHSE", "600837", "海通证券"));
exchange1.Instruments.Add(new InstrumentViewModel("SHSE", "601668", "中国建筑"));
ExchangeViewModel exchange2 = new ExchangeViewModel();
exchange2.ExchangeID = "SZSE";
exchange2.Instruments.Add(new InstrumentViewModel("SZSE", "000002", "万科A"));
exchange2.Instruments.Add(new InstrumentViewModel("SZSE", "000001", "平安银行"));
exchange2.Instruments.Add(new InstrumentViewModel("SZSE", "000623", "吉林敖东"));
exchange2.Instruments.Add(new InstrumentViewModel("SZSE", "002739", "万达电影"));
exchange2.Instruments.Add(new InstrumentViewModel("SZSE", "300642", "透景生命"));
Exchanges.Add(exchange1);
Exchanges.Add(exchange2);
}
public string BindData { get; set; } = "BindData";
public ObservableCollection Exchanges { get; set; }
}