C#と.Net3.5を使用して、Winformsデータグリッドビューへのデータバインディングを解決しようとしています。これは少し複雑で、コードを提供するいくつかのクラスが含まれています。
私はそのように定義されたインターフェースを持っています:
public interface MyElement : IEditableObject {
string Name { get; set; }
string Description { get; set; }
}
次に、次のように定義されたMyElementから継承するabstaractクラスがあります。
abstract public class MyElementAdapter : MyElement {
private string myName;
private string myDescription;
private ModelElement myParent;
public MyElementAdapter(MyElement parent) {
myName = "New_Element";
myDescription = string.Empty;
}
virtual public string Name {
get { return myName; }
set { myName = value; }
}
virtual public string Description {
get { return myDescription; }
set { myDescription = value; }
}
public MyElement Parent {
get { return myParent; }
set { myParent = value; }
}
public void BeginEdit() {
// code to begin edit
}
public void CancelEdit() {
// code to cancel edit
}
public void EndEdit() {
// code to end edit
}
}
そのように定義されたインターフェースタイプの一般的なリストがあります-その非常に基本的なものであり、MyElementsの一般的なリストを保持しているだけです。
public class MyElementList : List<MyElement> {
public MyElementList() {
}
}
次のように定義されたMyElementAdapterから派生したMyFieldという名前の継承されたクラスがあります。
public class MyField : MyElementAdapter {
private int size;
public MyField(MyElement parent) : base(parent) {
size = 1;
}
public string MyFieldName {
get { return this.Name; }
set { this.Name = value;}
}
public string MyFieldDescription {
get { return this.Description; }
set { this.Description = value;}
}
public int Size {
get { return size; }
set { size = value; }
}
}
MyElementListを使用するクラスがあります。MyFieldはリストタイプです。
public class MyRecordOfFields : MyElementAdapter {
private MyElementList myMembers;
public MyRecordOfFields(MyElement parent) : base(parent) {
myMembers = new MyElementList();
}
public MyElementList MyMembers {
get { return myMembers; }
set { myMembers = value; }
}
}
そして最後に、MyRecordOfFieldsタイプのオブジェクトを編集するために使用しているフォームがあります。
public class Form1 : Form {
private BindingSource bindingSource1;
private MyRecordOfFields myLocalFields;
private DataGridView dgv;
private Form1_Load() {
myLocalFields = new MyRecordOfFields(null);
MyField field1 = new MyField(null);
field1.MyFieldName = "Field_1";
field1.MyFieldDescription = "Description1";
field1.Size = 3;
myLocalFields.MyMembers.Add(field1);
MyField field2 = new MyField(null);
field2.MyFieldName = "Field_2";
field2.MyFieldDescription = "Description2";
field2.Size = 3;
myLocalFields.MyMembers.Add(field2);
MyField field3 = new MyField(null);
field3.MyFieldName = "Field_3";
field3.MyFieldDescription = "Description3";
field3.Size = 3;
myLocalFields.MyMembers.Add(field3);
bindingSource1 = new BindingSource();
bindingSource1.AllowNew = true;
dgv.AutoGenerateColumns = false;
int colIndex = dgv.Columns.Add("MyFieldName", "MyFieldName");
dgv.Columns[colIndex].DataPropertyName = "MyFieldName";
colIndex = dgv.Columns.Add("MyFieldDescription", "MyFieldDescription");
dgv.Columns[colIndex].DataPropertyName = "MyFieldDescription";
colIndex = dgv.Columns.Add("Size", "Size");
dgv.Columns[colIndex].DataPropertyName = "Size";
dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
dgv.AutoResizeColumns();
bindingSource1.DataSource = myLocalFields.MyMembers;
dgv.DataSource = bindingSource1;
dgv.Invalidate();
}
}
このフォームがロードされると、すべてがコンパイルされて実行されますが、フォームが表示されると、datagridviewには3行がありますが、すべて空白です。DatagridviewのデータソースをMyRecordOfFieldsクラスのMyElementListに直接設定しようとしていますが、リストに追加された行数を期待して何も表示されません。
datagridviewのデータソースをリストに設定せずに、そのリストの各要素をループで追加すると、データが適切に表示されます。
次の行:
bindingSource1.DataSource = myLocalFields.MyMembers;
ループに変更:
foreach (MyElement me in myLocalFields.MyMembers) {
// No casting needed due to inheritance
bindingSource1.Add(me);
}
また、ループに変更した後、基になるデータソースであるmyLocalFields(MyRecordOfFields.MyMembers)に追加、削除、および更新するためのイベントハンドラーを追加する必要がありました。
私のシナリオで何かが欠けているか、正しく実行されていませんか?インターフェイスと抽象クラスに少し関係していることは知っていますが、事前定義された実装から作業しているため、これらの基礎となる/基本的なクラスを変更することはできません。前もって感謝します。
- ローレンツ
更新: 私はいくつかの提案を試みましたが、何の役にも立ちません。だから私の質問はこれです:BindingSource1.DataSourceをMyRecordOfFields.MyMembersプロパティのMyElementLIstに設定することで、MyFieldの継承されたプロパティ(datagridview [columns]を設計したように)を公開することは可能ですか?
ここで、ガイダンスが必要です。MyElementはインターフェイスです。MyElementAdapterは、MyElementから派生した抽象です。MyElementListは、MyElementの汎用リストです。MyFieldはMyElementAdapterから派生しています。MyElementまたは任意の派生クラス(つまりMyField)をMyElementListに追加すると機能します。それでも、UIで公開したいのはこれらの派生クラスのプロパティ(datagridview、controlsなど)です。
UPDATE#2: datagridviewをMyElementListにバインドしたので、すべてが正常に機能しています。現在、myLocalFields.MyMembersリストの追加/削除/更新に取り組んでいます。次のコードでボタンを追加しました。
private void AddItem_Click(object sender, EventArgs e) {
MyField field1 = new MyField(null);
field1.MyFieldName = "Field_" + myLocalFields.MyMembers.Count + 1;
field1.MyFieldDescription = "Description" + myLocalFields.MyMembers.Count + 1;
field1.Size = myLocalFields.MyMembers.Count + 1;
myLocalFields.MyMembers.Add(field1);
((BindingSource)dataGridView1.DataSource).ResetBindings(false);
}
このメソッドを実行すると、基になるデータ(myLocalField.MyMembers)が変更されますが、bindingSource1とdataGridView1は変更されません。以前は、基になるデータの更新は、基になるデータとバインディングソースに対して行われていました。基になるデータに変更を加えて、そのデータをbindingsource/datagridviewに反映させたいと思います。
私は、以下がdatagridviewへの変更を処理すると考えましたが、そうではありません。
((BindingSource)dataGridView1.DataSource).ResetBindings(false);
datagridviewイベントを追加せずにdatagridviewを更新するために使用する必要がある別の方法はありますか?