2012-02-22 18 views
2

技術:.NET 4、C#の、WinFormsのは、Visual Studio 2010の単純な結合の.NETデータバインディング機能していない

私はバインディング学習データの処理にいると仕事にも、簡単な例を得ることができませんでした予想通り。私は現在のマウスカーソルの座標を示すためにバインドしているラベルを持つフォームを持っています。

public partial class Form1 : Form, INotifyPropertyChanged 
{ 
    [Bindable(true)] 
    private String cursorPosition; 
    public String CursorPosition 
    { 
     get 
     { 
      return cursorPosition; 
     } 

     set 
     { 
      cursorPosition = value; 
      NotifyPropertyChanged("CursorPosition"); 
     } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    public Form1() 
    { 
     InitializeComponent(); 
    } 

    private void Form1_MouseMove(object sender, MouseEventArgs e) 
    { 
     CursorPosition = "(" + Convert.ToString(e.X) + " , " + Convert.ToString(e.Y) + ")"; 
    } 

    private void NotifyPropertyChanged(String propertyName) 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 
} 

デザイナーから、Textプロパティをform1BindingSource-CursorPositionにバインドするためのラベルのデータバインディングを設定しました。私は何が欠けていますか?

編集:更新されたコードスニペット。

答えて

5

デザイナーから、Textプロパティをform1BindingSource - CursorPositionにバインドするラベルのデータバインディングを設定しました。私は何が欠けていますか?

form1BindingSource.DataSource = this; // (or whatever the real data source is) 

例えば:

は、設定しましたフォームのコンストラクタでInitializeComponentの後に?

(これはあなたのForm1インスタンスがデータソースであり、あなたがBindingSourceを経由して、それにコントロールを結合していることを前提としています。)


少数さらに詳細提案:

  1. フォーム自体をデータソースとして選択することは、やや珍しいことです。 IMHOバインドされたすべてのプロパティを別々のUI以外のデータオブジェクトに分割する方がよいでしょう。これにより、INotifyPropertyChanged実装の再利用可能な基本型を作成することができます。

  2. @rfmodulatorが彼の答えで言うように、BindableAttributeがフィールドに添付されています

    [Bindable(true)] 
    private String cursorPosition; 
    public String CursorPosition 
    … 
    

    おそらく、プロパティにそれを添付することを意図:

    private String cursorPosition; 
    [Bindable(true)] 
    public String CursorPosition 
    … 
    
  3. あなたセッターは次のようになります:

    set 
    { 
        if (!string.Equals(cursorPosition, value)  // + 
        {            // + 
         cursorPosition = value; 
         NotifyPropertyChanged("CursorPosition"); 
        }            // + 
    } 
    

    つまり、プロパティ値が実際に変更されたときにのみPropertyChangedイベントを発生させます。

  4. はおそらくこれにあなたのNotifyPropertyChanged方法を変更したい:

    private void NotifyPropertyChanged(String propertyName) 
    { 
        PropertyChangedEventHandler handler = PropertyChanged;   // + 
        if (handler != null)           // ~ 
        { 
         handler(this, new PropertyChangedEventArgs(propertyName)); // ~ 
        } 
    } 
    

    これがあるので変更nullチェックと呼び出しの間に理論的にはPropertyChangedでし。イベントデリゲートのローカルコピーを作成することで、この理論上の可能性を排除できます。

    PS:ジェフリー・リヒターは、「C#の経由CLR」彼の著書で指摘するように、ローカル変数がまだかなり十分ではありません、正確には:理想的には、あなたはhandlerからInterlocked.CompareExchange(ref PropertyChanged, null, null)(代わりに、単にPropertyChanged)を割り当てると思いますので、このメソッドを使用すると、JITコードジェネレータがローカル変数(IIRC)を最適化できなくなります。

+0

ありがとう! 'DataSource'を設定しないのは、私が行方不明になっていたものであり、ドキュメントを見ても覚えていません。私はノンビューコードをあなたが示唆したように適切なコントローラにリファクタリングしました。私はあなたの新しいセッターとNotifyPropertyChangedメソッドがはるかに優れていることに同意します。 – Noren

2

PropertyChangedイベントを発生させたいと思いますか?プロパティの値ではなく、Backing変数の値をMouse_Moveに設定しています。その結果、NotifyPropertyChangedの呼び出しは呼び出されません。

+0

良いキャッチ。変更を反映するようにコードを更新しましたが、ラベルはまだ更新されません。 – Noren

+0

NotifyPropertyChangedが呼び出されたときにPropertyChangedに値があるかどうかをチェックします。 –

+0

いいえ、そうではありません - それはnullです。私はどこが初期化されているのかわかりません。私がMSDN(http://msdn.microsoft.com/en-us/library/ms229614.aspx)で見つけたリファレンスは、私のコードと同じです。 – Noren

1

データバインディングが変更通知をリッスンするXXXChangedイベントパラダイムに依存しますので、あなたはcomponentscontrolsformsにINotifyPropertyChangedのを実装するべきではありません。内部的には、データバインディングはproperty descriptorsを使用して変更イベントを待ち受けます。彼らはPropertyDescriptor.SupportsChangeEvents propertyのドキュメントの変更をクラスがどのように検出したかをヒントします。これは、winformsデータバインディングの履歴と関係しています。 XXXChangedは.NET 2.0より前にデータ通知を行う方法でした&変更通知。 INotifyPropertyChangedは、2.0で導入され、XXXChangedパターンのために導入されました。

SupportsChangeEventsプロパティは、このプロパティの値の変更通知は、コンポーネント自体からなど、プロパティ記述子の外側から生じ得るかどうか、または通知のみSetValueメソッドに対して行われたダイレクトコールに由来するかどうかを示しています。たとえば、コンポーネントはINotifyPropertyChangedインタフェースを実装することも、このプロパティの明示的なnameChangedイベントを持つこともできます。

1

フィールドにBindable属性を設定していますが、そのプロパティーを引数としてNotifyPropertyChangedを呼び出しています。

関連する問題