C#winform數據綁定


1.DataBindings

 控件基類(Control),有一個DataBindings對象,它是一個ControlBindingCollection類,這個類繼承與BindingsCollection,里面有一個Binding的列表對象,其中Binding對象是一個記錄了屬性名,數據源,數據成員等的對象。


 建立一個People類,用於數據綁定:

public class People
{
    public string Name { get; set; }
    public int Age { get; set; }
}

 建立winform窗體程序,放入兩個TextBox控件:

public partial class Form1 : Form
{
    People _people = new People();
    public Form1()
    {
        InitializeComponent();
        _people.Name = "QQ";
        _people.Age = 3;
        this.tbName.DataBindings.Add("Text", _people, "Name");
        this.tbAge.DataBindings.Add("Text", _people, "Age");
    }
}

 this.tbName.DataBindings.Add("Text", _people, "Name")   表示將_people的Name屬性的值綁定到tbName的Text屬性上,每個屬性只能綁定一個源。

如果控件是如上述代碼那樣綁定數據源的話,修改控件的值可以影響源數據的值,即修改tbName的Text值時_people的Name值也會改變,但是修改_people的Nam值時tbName的Text值並不會改變。所以就要修改People類,如下例所示:


public class People : INotifyPropertyChanged
{
    string _name;
    int _age;

    public string Name
    {
        get { return _name; }
        set
        {
            _name = value;
            OnPropertyChanged(nameof(Name));
        }
    }

    public int Age
    {
        get { return _age; }
        set
        {
            _age = value;
            OnPropertyChanged(nameof(Age));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string propertyName)  //屬性變更通知
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

 People繼續INotifyPropertyChanged接口,並在對應屬性執行set時觸發屬性變更事件,會將變更后的值顯示到所綁定的控件上。

PS:這里用到了nameof關鍵字是為了不想用字符串,因為一旦改變了屬性名稱,若是用的是字符串它不會自己改變,控件綁定的時候也可以這樣表示。nameof只能在6.0以上版本才可以使用,若是一下版本,可參考這篇博文 6.0版本以下nameof

2.Binding 

Binding:代表某對象屬性值和某控件屬性值之間的簡單綁定。 

this.tbName.DataBindings.Add("Text", _people, "Name");  就表示Add一個Binding,除了設置這三個參數外,還可以設置其他的參數。

PropertyName 要綁定到的控件屬性的名稱  
DataSource 綁定的數據源  
DataMember 要綁定到的屬性或列表  
FormattingEnabled 指示是否對控件屬性數據應用類型轉換和格式設置 false:不執行格式化,即FormatString和FormatInfo無效
DataSourceUpdateMode 指示將綁定控件屬性的更改傳播到數據源的時間

    枚舉類型:

  • OnValidation  當確定修改完成后更新數據源
  • OnPropertyChanged  每當控件屬性的值更改時,將更新數據源
  • Never  永遠不會更新數據源並且不分析、 驗證或重新格式化文本框控件中輸入的值
NullValue 設置控件屬性為null時的替代值 當綁定的值為null時替代顯示的值
FormatString 指示如何顯示值的格式說明符 要格式化的說明符,例:“X4”,將整數格式化為4位十六進制數
FormatInfo 可提供自定義格式設置行為  

例:this.tbAge.DataBindings.Add(nameof(this.tbAge.Text), _people, nameof(_people.Age), true, DataSourceUpdateMode.OnPropertyChanged, "0", "X4"); 

3.BindingSource 

BindingSource:封裝窗體的數據源 


我們有的時候需要建立一個自定義控件用來顯示或者設置某個對象的屬性值,就可以用到BindingSource: 

public partial class UserControl1 : UserControl
{
    public UserControl1()
    {
        InitializeComponent();
        this.bindingSource1.DataSource = typeof(People);
        People p = this.bindingSource1.DataSource as People;
        this.tbName.DataBindings.Add(nameof(this.tbName.Text), this.bindingSource1, nameof(p.Name));
        this.tbAge.DataBindings.Add(nameof(this.tbAge.Text), this.bindingSource1, nameof(p.Age), true, DataSourceUpdateMode.OnValidation);
        this.errorProvider1.DataSource = this.bindingSource1;
    }

    public People People
    {
        get { return this.bindingSource1.DataSource as People; }
        set
        {
            this.bindingSource1.DataSource = value;
        }
    }
}

 這里建立一個ErrorProvider,用來校驗BindingSource數據的正確性,例如這里的Age,如果設置為非Int類型,就會提示信息。

BindingSource有個DataMember屬性,用來設置要顯示的數據成員,例如DataSet為Source時,就可以通過設置DataMember的值來指定顯示的是哪個DataTable。


下面將BindingSource應用到DataGridView控件上: 

public partial class UserControl1 : UserControl
{
    public UserControl1()
    {
        InitializeComponent();
        List<People> listPeople = new List<People>
        {
            new People{ Name = "A", Age = 1 },
            new People{ Name = "B", Age = 2 },
            new People{ Name = "C", Age = 3 },
        };
        this.bindingSource1.DataSource = listPeople;
        this.dataGridView1.DataSource = this.bindingSource1;
    }

    private void btnAdd_Click(object sender, EventArgs e)
    {
        //this.bindingSource1.AddNew();
        this.bindingSource1.Add(new People { Name = "GG", Age = 34 });
    }

    private void btnUpdate_Click(object sender, EventArgs e)
    {
        People p = this.bindingSource1.Current as People;
        p.Name = "U";
    }

    private void btnDelete_Click(object sender, EventArgs e)
    {
        //this.bindingSource1.RemoveCurrent();   //移除資源當前項
        foreach (DataGridViewRow row in this.dataGridView1.SelectedRows)
        {
            this.bindingSource1.Remove(row.DataBoundItem);
        }
    }

    private void btnSort_Click(object sender, EventArgs e)
    {
        this.bindingSource1.Sort = "Name desc";
        //this.bindingSource1.RemoveSort();  //去除排序,恢復顯示
    }

    private void btnSelect_Click(object sender, EventArgs e)
    {
        this.bindingSource1.Filter = "Age = '2'";
        //this.bindingSource1.RemoveFilter();  //去除篩選,恢復顯示
    }
}

通過上述代碼可以驗證,可以通過操縱BindingSource來控制DataGridView的顯示,增刪查改都適用。(如果BindingSource綁定的是集合之類時,排序和篩選不能使用,必須實現IBindingListView接口,如果綁定的是DataTable就可以) 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM