web-dev-qa-db-ja.com

C#のオブジェクトへのデータバインディング

Objective-c/cocoaは、コントロールのプロパティ(つまり、テキストボックス内のテキスト)をオブジェクトのプロパティにバインドできるバインドの形式を提供します。この機能をC#w/.Net3.5で複製しようとしています。

MyClass.csファイルに次の非常に単純なクラスを作成しました。

class MyClass
{
    private string myName;

    public string MyName
    {
        get
        {
            return myName;
        }

        set
        {
            myName = value;
        }
    }

    public MyClass()
    {
        myName = "Allen";
    }
}

また、1つのテキストボックスと1つのボタンを備えた単純なフォームを作成しました。フォームコード内でMyclassのインスタンスを1つ初期化し、プロジェクトをビルドしました。 Vs2008のDataSource Wizardを使用して、オブジェクトに基づいてデータソースを作成することを選択し、MyClassアセンブリを選択しました。これによりデータソースエンティティが作成されました。テキストボックスのデータバインディングをこのデータソースに変更しました。ただし、期待される結果(テキストボックスの内容が「allen」になる)は達成されませんでした。さらに、テキストボックスにテキストを入力しても、オブジェクトのnameプロパティは更新されません。

私はここで基本的な何かが欠けていることを知っています。ある時点で、フォームコード内で初期化したMyClassクラスのインスタンスをテキストボックスに関連付ける必要がありますが、それは発生していません。私がオンラインで見たものはすべて、オブジェクトでDataBindingを使用することを註解しているようです(またはマークが完全に欠落している)ので、どんな助けでも大歓迎です。

編集:

回答で学んだことを利用して、Visual Studioで生成されたコードを調べたところ、次のようになりました。

this.myClassBindingSource.DataSource = typeof(BindingTest.MyClass);

私がそれをコメントアウトして代用した場合:

this.myClassBindingSource.DataSource = new MyClass();

期待どおりの動作が得られます。 VSによって生成されるデフォルトのコードがそうであるのはなぜですか?これが機能する方法よりも正しいと仮定すると、VSが生成した範囲内で機能するようにコードを変更するにはどうすればよいですか?

19
Allen

テキストボックスのデータソースを新しいデータソースとして割り当てる必要があります。ただし、さらに、データソースのデータソースをクラスのインスタンスとして割り当てる必要があります。

MyDataSource.DataSource = new MyClass();
TextBox1.DataSource = MyDataSource;

それはあなたの最初のパスのために働くはずです。他の人が述べているように、バックグラウンドプロセスを介してクラスのプロパティを変更する場合は、クラスに追加のインターフェイス(INotifyPropertyChangedなど)を実装する必要がある場合があります。

フォームを介してプロパティを更新するだけの場合は、この手順は必要ありません。

15
Jason Coyne

MyClassタイプにINotifyPropertyChangedインターフェイスを実装する必要があります。

public class MyClass : INotifyPropertyChanged
{
   private string _myName;

   public string MyName
   {
       get { return _myName; }
       set
       {
          if( _myName != value )
          {
              _myName = value;
              OnPropertyChanged("MyName");
          }
       }
   }

   public event PropertyChangedEventHandler PropertyChanged;

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

このインターフェイスは、単純なデータバインディングをサポートする場合、DataBindingインフラストラクチャに必要です。 INotifyPropertyChangedインターフェイスは、プロパティが変更されたことを「バインディング」に通知するために使用されるため、DataBindingインフラストラクチャはそれに応じて動作できます。

次に、MyNameプロパティをテキストボックスのTextプロパティにデータバインドできます。

12

DataBinding.Add("TEXT", myObject, myObjectProperty)メソッドでエラーメッセージが表示されます

これはおそらく、プロパティ宣言に明示的な{get; set;}がないためです。

悪い:

public string FirstName;    //<-- you will not be able to bind to this property!

良い:

public string FirstName { get; set; }
3
Ron Maman

MyNameプロパティにBindable属性が必要なようです(Frederikの提案にも従ってください)。

   [System.ComponentModel.Bindable(true)] 
   public string MyName
   {
       get { return _myName; }
       set
       {
          if( _myName != value )
          {
              _myName = value;
              OnPropertyChanged("MyName");
          }
       }
   }

経由: http://support.Microsoft.com/kb/32741

0
Cᴏʀʏ

目の前にコードはありませんが、データソースはコレクションのようなものだと思います。 MyClassのインスタンスをデータソースに追加する必要があり、それがフォームフィールドのバインド先になります。データソースを介してMyClassの複数のインスタンスに移動するためのメソッドもありますが、それが必要なようには思えません。 DataSourceのドキュメントを確認してください。

派手なインターフェースを実装する必要はないと思います。いくつかの値を変更した後、現在のアイテムを更新または再バインドできるメソッドがデータソースにあることを覚えているようです。

0
Don Kirkby
using System.Collections.Generic;

public class SiteDataItem
{ 
private string _text; 
private string _url; 
private int _id; 
private int _parentId;

public string Text
{  
    get 
    { 
        return _text; 
    }  
    set 
    { 
        _text = value;
    } 
}

public string Url 
{  
    get 
    { 
        return _url; 
    }  
    set 
    { 
        _url = value;
    } 
}
public int ID 
{  
    get 
    { 
        return _id;
    }  
    set 
    { 
        _id = value;
    } 
}
public int ParentID 
{  
    get 
    { 
        return _parentId;
    } 
    set 
    { 
        _parentId = value;
    } 
}
public SiteDataItem(int id, int parentId, string text, string url)
{  
    _id = id;
    _parentId = parentId;
    _text = text;
    _url = url;
}

public static List<SiteDataItem> GetSiteData() 
{  
    List<SiteDataItem> siteData = new List<SiteDataItem>();
    siteData.Add(new SiteDataItem(1, 0, "All Sites", ""));  
    siteData.Add(new SiteDataItem(2, 1, "Search Engines", ""));
    siteData.Add(new SiteDataItem(3, 1, "News Sites", ""));
    siteData.Add(new SiteDataItem(4, 2, "Yahoo", "http://www.yahoo.com"));
    siteData.Add(new SiteDataItem(5, 2, "MSN", "http://www.msn.com"));  
    siteData.Add(new SiteDataItem(6, 2, "Google", "http://www.google.com"));  
    siteData.Add(new SiteDataItem(7, 3, "CNN", "http://www.cnn.com"));  
    siteData.Add(new SiteDataItem(8, 3, "BBC", "http://www.bbc.co.uk"));  
    siteData.Add(new SiteDataItem(9, 3, "FOX", "http://www.foxnews.com"));
    return siteData; 
}
}

詳細については、チュートリアルdapforを読むことができます。 com

0
Alastairgraeme