2010-07-01 50 views
1

我真的愛上了整個.Net數據綁定方案......但顯然還是有一些問題。假設我的類有一個名爲Susan的double類型成員變量。那麼有似乎沒有綁定Susan到一個文本框SusanText直接的方式,因爲綁定看起來像這樣C#數據綁定類變量

SusanText.DataBindings.Add("Text",datasource,"Property")

而且Susan是不是一個性質。所以我可以讓Susan成爲一個公共財產,但這有點臭...如果我想保持Susan隱藏? (我想我可以讓Susan成爲某個內部類的私人實例的公共屬性......但是這對於一點點雙重工作來說有很多工作。)但是,我遇到了一個更大的問題,所以爲了爭論起見,讓我們繼續並做到這一點:

private double Susan_; 
public double Susan{ get; set;} 
... 
SusanText.DataBindings.Add("Text",this,"Susan") 

然後,一切似乎按預期工作。如果我改變SusanText,則Susan相應地改變。但是,當我直接更改Susan時,問題就出現了。我想要自動更新SusanText。所以我懷疑我需要使Susan成爲實現某種IBindable接口的double的子類,以便如果Susan的數據綁定爲SusanText,則說明相應的事件已註冊,並且Susan會在修改後通知其他人。

要讓Susan做我想讓她做的事情,最簡單的方法是什麼?

謝謝!

回答

3

DataBinding期望它綁定的類提高INotifyPropertyChanged以指示某個值已被更改並需要重新讀取;不幸的是,實現這個過程仍然需要一些手工編碼(或者像PostSharp到IL的東西,編織必要的代碼)。

所以,爲了支持數據綁定,你不能使用自動實現的屬性,或者直接綁定到字段上 - 既沒有機會引發必要的事件(綁定會起作用,但值不會更新時更改)。

DataBinding的另一個缺點是它不考慮線程。如果後臺線程修改了一個數據綁定值,那麼數據綁定將嘗試進行跨線程調用來更新UI - 這是不好的。我發現的最佳解決方法是讓可綁定類保存其UI的實例Synchronization Context,這將允許您確保在UI線程上調用UI的更新。

using System.ComponentModel; 

namespace MyWebGrocer.Uma.UI 
{ 
    public class BoundClass : INotifyPropertyChanged 
    { 
    private string _Name; 

    private int _Age; 

    public event PropertyChangedEventHandler PropertyChanged; 

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

    public int Age 
    { 
     get 
     { 
     return _Age; 
     } 
     set 
     { 
     _Age = value; 
     OnPropertyChanged("Age"); 
     } 
    } 

    protected void OnPropertyChanged(string propertyName) 
    { 
     var propertyChanged = PropertyChanged; 
     if (propertyChanged != null) 
     { 
     PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 
    } 
} 

我知道這一切聽起來令人沮喪 - 數據綁定的這些缺點是困難的。但是,在它們表現爲更大的問題之前,最好先意識到這些問題並予以補償。

+0

「你不能使用自動實現的屬性」好了,你可以,你就必須設置火後INPC財產。似乎有點奇怪,但它有時候是一種有用的模式,比如當你想要將多個屬性作爲僞事務的一部分來更新時。 – Will 2010-07-01 17:02:10

+1

@你可以 - 但是有一個消費類(B)在數據綁定類(A)上調用一個方法,使(A)引發一個事件,發出腥味。 .NET中的事件是特殊的代表,因爲它們只是有意從課堂內部被解僱 - 需要外部組件來觸發事件,這是乞求人們忘記的事情。海事組織最好做額外的工作,並讓數據綁定班能夠提高自己的事件。 – STW 2010-07-01 17:06:37

+0

@stw只是一個選項,只是一個選項。無論如何,我都會使用DependencyObjects。更容易綁定的屬性。 – Will 2010-07-01 17:09:46

0

很難告訴你一個最簡單的方法,而不知道你的代碼是如何組合在一起的。如果你在代碼中設置綁定,看起來你仍然在以困難的方式做事。

這裏是最簡單的方法:

namespace MyProject 
{ 
    public sealed class ViewModel : DependencyObject //handles all databinding voodoo 
    { 
     public string Susan 
     { 
      get { return (string)GetValue(SusanProperty); } 
      set { SetValue(SusanProperty, value); } 
     } 

     public static readonly DependencyProperty 
      SusanProperty = DependencyProperty.Register 
       ("Susan", typeof(string), 
       typeof(ViewModel)); 
    } 
} 

,並在XAML:

<Window.DataContext> 
    <ViewModel xmlns="clr-namespace:MyProject" /> 
</Window.DataContext> 
<Grid> 
    <TextBox Text="{Binding Susan}" /> 
</Grid> 
+1

不幸的是,對於像我這樣的新手來說,這裏只有一點點巫術。我還不知道有關xaml的任何信息。它看起來非常酷且有用,但現在沒有人願意付錢給我學習它。不過謝謝。 – JnBrymn 2010-07-01 17:39:29

+0

@John坦率地說,它不難學習,而且你可以看到綁定比在代碼中完成要容易得多。此外,通過編輯器增強功能(如設計時數據),您可以使用屬性窗口根據實際的數據上下文類型創建綁定。水太棒了,進來吧。 – Will 2010-07-01 18:15:09