2016-10-02 47 views
5

我有一個對象綁定到使用C#WinForms(定位.NET 4.5.2)的窗體上的控件。我已經實現了INotifyPropertyChanged,並且當我修改此對象的Property時,它按照預期更新了Form的控件。但是,當我將此對象的實例更改爲新實例時,即使嘗試修改特定的屬性,它也不會再更新控件。當我將一個新對象實例指定給綁定變量時,數據綁定不起作用

class User : INotifyPropertyChanged 
{ 
    string _name = ""; 

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

    public event PropertyChangedEventHandler PropertyChanged; 

    protected void OnPropertyChanged(string property) 
    { 
     PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property)); 
    } 

    public User() { } 

    public User(string name) 
    { 
     Name = name; 
    } 

    public User(User otherUser) 
    { 
     Name = otherUser.Name; 
    } 
} 

和窗體上我有

User currentUser = new User("Example Name"); 
lblName.DataBindings.Add("Text", currentUser, "Name"); 

哪些更新正確。我可以使用currentUser.Name = "Blahblah";更改名稱,它工作正常。當我嘗試撥打currentUser = new User("New Name");時,無論我做什麼,它都不會再更新。

我的理解是,對象的特定實例是控件綁定的內容。我的主要目標是不必手動遍歷更大對象的每個屬性,並在每次更改實例時手動更改所有內容。

我的問題:有沒有一種方法來更改對象的實例,而無需去除綁定到控件?

lblName.DataBindings.Add("Text", currentUser, "Name"); 

相反,你需要一些中介:

回答

2

爲了獲得所需的行爲,你不應該直接像你目前做綁定到具體實例。最簡單的就是使用BindingSource組件。

一個BindingSource字段添加到窗體:

private BindingSource dataSource; 

對其進行初始化和控件綁定到它一個時間(通常在形式上Load事件):

dataSource = new BindingSource { DataSource = typeof(User) }; 
lblName.DataBindings.Add("Text", dataSource, "Name"); 
// ... 

現在,只要你想綁定到User實例,只需將其分配給BindingSourceDataSource屬性:

初始:

dataSource.DataSource = new User("Example Name"); 

後:

dataSource.DataSource = new User("New Name"); 
+0

這工作完美。謝謝! – pfthroaway

2

伊萬展示瞭如何解決這個問題。在這個答案中,我會試着告訴你什麼是問題,以及它爲什麼這樣工作。

簡短的回答

你的標籤綁定到一個對象不變量。該變量就像一個指向該對象的指針。因此,替換該變量對您的標籤用作數據源的對象沒有任何影響。只是變量指向新對象。但是你的標籤正在使用之前的對象。它有自己的指向前一個對象的指針。

考慮到這些事實,就知道發生了什麼:

  1. User currentUser = new User("Example Name");

    當您分配一個對象變量,實際上變量指向的對象。

  • lblName.DataBindings.Add("Text", currentUser, "Name");
    你執行數據綁定到對象。控件將綁定到對象而不是變量。
  • currentUser.Name = "Blahblah";

    你改變Name財產的價值,因爲你實現INotifyPropertyChanged的控制將被通知的變化,並且將刷新其Text

  • 但主要的聲明,如你預期沒有工作:

  • currentUser = new User("New Name");

    在這裏,你所做的currentUser可變點到另一個對象。它與它指向的前一個對象沒有任何關係。它只是指向另一個對象。

    您添加到標籤的Binding仍然使用先前的對象。

    因此,沒有任何通知是正常的,因爲標籤使用的對象沒有改變。

  • BindingSource如何解決問題?

    BindingSource提高,當你分配一個新的對象到其DataSourceListChanged事件,它使BindingObjectDataSource獲取新的價值,並刷新Text財產。你可以看看這篇文章:How to make a binding source aware of changes in its data source?

    +0

    這是非常翔實的。謝謝。 – pfthroaway

    +0

    不客氣:) –

    +0

    好的解釋! –