C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[5]: InitializeComponent()でのコード生成


(過去ログ 12 を表示中)

[トピック内 6 記事 (1 - 6 表示)]  << 0 >>

■3024 / inTopicNo.1)  InitializeComponent()でのコード生成
  
□投稿者/ しろやぎ (1回)-(2007/04/20(Fri) 23:57:11)

分類:[C# (Windows)] 

デザイナによるコード生成に関しての相談です。

あるクラス(Recordクラス)のプロパティの設定に特化したRecordSettingGridViewを作ろうとしています。
RecordSettingGridViewは内部にRecordコレクションの参照を持っていて、かつ、DataGridViewを継承しています。
つまり、以下のような感じです。

// 1件のレコード
class Record
{
 private string name_;
 private int age_;
 private bool sex_;

 // 名前
 public string Name
 {
  get{ return this.name_; }
  set{ this.name_ = value; }
 }

 // 年齢
 public int Age
 {
  get{ return this.age_; }
  set{ this.age_ = value; }
 }

 // 性別
 public bool Sex
 {
  get{ return this.sex_; }
  set{ this.sex_ = value; }
 }

}

// Recordのプロパティを編集するDataGridView
class RecordSettingGridView : DataGridView
{
 // いじらない
 private List<Record> recordsOrg_;
 
 // 変更するためのRecords
 private List<Record> records_;
 private List<Record> Records
 {
  get{ return this.records_; }
  set
  {
   this.recordsOrg_ = value;

   // ディープコピー(編集にはこっちを使う)
   this.records_ = new List<Record>();
   for(int i=0;i<vlalue.Count;i++)
    this.records_.Add(value[i].Clone() as Records);

   this.RowCount = this.records_.Count;
  }
 }

 // その他のメンバ...

 // コンストラクタ
 public RecordSettingGridView() : base()
 {
  // 列を生成
  this.AddColumns();
 }

 // 列を生成
 private void AddColumns()
 {
  DataGridViewTextBoxColumn colName = new DataGridViewTextBoxColumn();
  colName.HeaderText = "名前";
  colName.Name = "colName";
  colName.ValueType = typeof(string);
  this.Columns.Add(colName);

  // 他の列も同様に...
 }

 // OnCellValueNeededとかその他もろもろ...
}

これをFrom1に貼り付けて使おうとしているのですが、以下のような問題があります。

問題点1「AddColumns()の内容が、勝手にInitializeComponent()に生成される」
このRecordSettingGridViewをフォーム(Form1)に貼り付けると、
Form1.Designer.csの中のInitializeComponent()の中で勝手に列が追加されます。
もちろん実行時にもう一度AddColumns()が実行されるので、
結果として同じ列が2個ずつ表示されることになります。

問題点2「InitializeComponent()内にRecords = nullが生成される」
Formに貼り付けるコントロールは空コンストラクタを持っていなくてはならないので、
RecordSettingGridViewのコンストラクタを空にしています。
(というか、引数ありのコンストラクタを持っていても、
InitializeComponent()では既定のコンストラクタ呼び出されるわけですよね)
んで、必要な情報(Recordのコレクション)はpublicプロパティで受け取るようにしています。
だもんで、またまた勝手にInitializeComponent()内でRecordsをnullにしてくれます。


InitializeComponent()内に勝手にコードを生成させないようにするにはどうしたらいいですか?
Form1をデザインする画面を開くたびに、InitializeComponent()を勝手に書き換えられ、
そのたびに該当箇所を削除しています。いい加減うんざり(;Д;)

どなたか解決法を教えてください。
よろしくお願いします。

デザイナによるコード生成の問題っちゅうか、
どんなコード生成されても死なないコード書きなさい、ってことですかね?
引用返信 編集キー/
■3062 / inTopicNo.2)  Re[1]: InitializeComponent()でのコード生成
□投稿者/ しろやぎ (2回)-(2007/04/22(Sun) 15:04:31)
いろいろ調べてたら、問題点2に対しては解決策を見つけられました。
プロパティにDesignerSerializationVisiblityAttribute属性を指定してやれば良さげです。
具体的にコードで示すと

[DesignerSerializationVisiblity(DesignerSerializationVisiblity.Hidden)]
public List<Record> Records
{
 get{ return this.records_; }
 set{ /* ほげほげ */ }
}
こんな感じでしょうか。(前の書き込みでは間違ってprivateにしてました)


いまだに問題点1に関しては解決していません。

// コンストラクタ
public RecordSettingGridView() : base()
{
 // デザインモードでなければ列を生成
 if (!this.DesignMode) this.AddColumns();
}
こんな感じで回避できるかと思いきや、DesignModeプロパティはコンストラクタの中では働いてくれないそうで。
んんん...、どうしたものか...。

引き続き、書き込み期待しております。
よろしくお願いします。

引用返信 編集キー/
■3066 / inTopicNo.3)  Re[2]: InitializeComponent()でのコード生成
□投稿者/ aoa (25回)-(2007/04/22(Sun) 21:05:10)
こんばんは。
確かにバグっぽいですが、
直接InitializeComponentを修正なくても
デザイナからプロパティ-Columnsで列を削除すれば良さそうですよ。

こちらでフィードバックしてくれています。
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=37638&forum=7&
引用返信 編集キー/
■3077 / inTopicNo.4)  Re[3]: InitializeComponent()でのコード生成
□投稿者/ しろやぎ (3回)-(2007/04/23(Mon) 11:09:28)
aoaさん、書き込みありがとうございます。

確かにデザイナからプロパティ-Columnsで列を削除する方が、
Form1.Designer.csのコードの該当箇所を削除するより手間が省けますね。

リンク先の掲示板では継承じゃなくてUserControl使ってコンポジションで、
というご意見もあるのでやってみますね。
(でもできれば継承のほうが... ボソッ)

後ほど結果を書きます。
書き込みもまだ期待していますよ。
よろしくお願いします。

引用返信 編集キー/
■3256 / inTopicNo.5)  Re[4]: InitializeComponent()でのコード生成
□投稿者/ しろやぎ (4回)-(2007/04/28(Sat) 00:07:13)
すっかり遅くなりました。すんません。

UserControl継承して、コンポジションでやるとこんな感じでしょうか。
this.grdMainはDataGridViewですよ。
RecordSettingsGridView.Designer.csは省略です。
必要なイベント・プロパティは自分で用意しなくてはなりませんね。

public partial class RecordSettingsGridView : UserControl
{
 // 編集しないデータ
 private Records recordsOrg_;

 // 編集用のデータ
 private Records records_;

 // コンストラクタ
 public RecordSettingsGridView()
 {
  InitializeComponent();
  this.InitDataGridView();
  this.AddColumns();
 }

 // グリッドの設定
 private void InitDataGridView()
 {
  this.grdMain.VirtualMode = true;
  this.grdMain.AllowUserToAddRows = false;
  this.grdMain.AllowUserToDeleteRows = false;
  this.grdMain.EnableHeadersVisualStyles = false;
 }

 // 編集するデータ
 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
 public Records Records
 {
  get { return this.records_; }
  set
  {
   this.recordsOrg_ = value;
   this.records_ = value == null ? null : value.Clone() as Records;

   this.grdMain.Rows.Clear();
   this.grdMain.RowCount = value == null ? 1 : value.Count;
  }
 }

 // 列を追加
 private void AddColumns()
 {
  this.grdMain.Columns.Clear();

  DataGridViewTextBoxColumn colName = new DataGridViewTextBoxColumn();
  colName.HeaderText = "名前";
  colName.Name = "colName";
  colName.ValueType = typeof(string);
  this.grdMain.Columns.Add(colName);

  DataGridViewTextBoxColumn colAge = new DataGridViewTextBoxColumn();
  colAge.HeaderText = "年齢";
  colAge.Name = "colAge";
  colAge.ValueType = typeof(int);
  this.grdMain.Columns.Add(colAge);

  DataGridViewCheckBoxColumn colSex = new DataGridViewCheckBoxColumn();
  colSex.HeaderText = "性別";
  colSex.Name = "colSex";
  colSex.ValueType = typeof(bool);
  this.grdMain.Columns.Add(colSex);
 }

 // データが必要になった
 private void grdMain_CellValueNeeded(object sender, DataGridViewCellValueEventArgs e)
 {
  int colIndex = e.ColumnIndex;
  int rowIndex = e.RowIndex;

  // ありえないセルならば何もしない
  if (this.grdMain.ColumnCount <= colIndex) return;
  if (this.grdMain.RowCount <= rowIndex) return;

  string colName = this.grdMain.Columns[colIndex].Name;
  switch (colName)
  {
   // 名前
   case "colName":
    e.Value = this.Records[rowIndex].Name;
    break;

   // 年齢
   case "colAge":
    e.Value = this.Records[rowIndex].Age;
    break;

   // 性別
   case "colSex":
    e.Value = this.Records[rowIndex].Sex;
    break;

   default:
    break;
  }

  return;
 }

 // セルの値を保存
 private void grdMain_CellValuePushed(object sender, DataGridViewCellValueEventArgs e)
 {
  int colIndex = e.ColumnIndex;
  int rowIndex = e.RowIndex;

  // ありえないセルならば何もしない
  if (this.grdMain.ColumnCount <= colIndex) return;
  if (this.grdMain.RowCount <= rowIndex) return;

  string colName = this.grdMain.Columns[colIndex].Name;
  switch (colName)
  {
   // 名前
   case "colName":
    this.Records[rowIndex].Name = (string)e.Value;
    break;

   // 年齢
   case "colAge":
    this.Records[rowIndex].Age = (int)e.Value;
    break;

   // 性別
   case "colSex":
    this.Records[rowIndex].Sex = (bool)e.Value;
    break;

   default:
    break;
  }

  return;
 }
}

引用返信 編集キー/
■3296 / inTopicNo.6)  Re[5]: InitializeComponent()でのコード生成
□投稿者/ しろやぎ (8回)-(2007/05/01(Tue) 23:32:32)
解決チェックです。
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -