- PR -

プロパティのListをシリアル化?

投稿者投稿内容
KT工房
常連さん
会議室デビュー日: 2006/06/20
投稿数: 49
投稿日時: 2008-12-15 10:49
いつもお世話になっております。

現在VB.Net2005にて開発していますが、問題にぶつかってしまいました。

やりたいことは、パネルを継承したクラスにList型の変数を2つ用意して、
デザイン時にプロパティでリストの内容を編集できるようにしたいのです。

Listの内容は1つはColor型のリスト、2つ目は独自のクラス型のリストです。

Color型のリストに関しては何もしなくても、プロパティが編集できて内容も保存されます。
独自のクラス型のほうは、そのままではプロパティの編集ができなかったので、
プロパティ宣言の頭に ↓ をつけることにより編集可能となりました。

<DesignerSerializationVisibility(DesignerSerializationVisibility.Content)>


これで、問題解決かな?と思っていたのですが、このListにデフォルト値を持たせると別の問題が発生しました。

Newのタイミングで各Listにデフォルト値をセットしたのですが、
実際に画面に貼り付けた際に、Listにデフォルト値が大量にセットされていました。
どうもデザイナで編集している時に、デフォルト値のAddが走っているような感じなのですが・・・。

Color型のListは増えないのですが、独自クラス型のListは同じデフォルト値が何度かAddされています。
デフォルト値のセットは同じ箇所でやっているので、両方増えるのならばわかるのですが。

貼り付けた画面のデザイナを見たところ、Color型のListはリソースから取得した値を代入していました。
独自クラス型のListはListのアイテムを生成して、Addしていました。
なので、大量にデフォルト値のアイテムが生成されています。

色々調べているのですが、いまいちヒントになりそうな情報を見つけられません。
TypeConverter や Collection を使わないとダメなんでしょうか?

よろしくお願いします。
indigo-x
大ベテラン
会議室デビュー日: 2008/02/21
投稿数: 207
お住まい・勤務地: 太陽の塔近く
投稿日時: 2008-12-15 13:58
DesignModeプロパティを見ればよいのでは。

http://msdn.microsoft.com/ja-jp/library/system.componentmodel.component.designmode(VS.80).aspx

KT工房
常連さん
会議室デビュー日: 2006/06/20
投稿数: 49
投稿日時: 2008-12-15 17:52
>indigo-x さん

返信ありがとうございます。

デザイン時は動作させないようにするということでしょうか?
現象としてはデザイン時にのみこの現象が発生しているかがわかりません。
Addメソッド自体が、Newにしか記述していないので。
オブジェクト生成の時しか走らないはずなのですが・・・。

私の希望としては、Color型のリストのように、リソースに保存できないかと考えています。
Toshi
ベテラン
会議室デビュー日: 2007/09/18
投稿数: 68
お住まい・勤務地: 関東のどっか
投稿日時: 2008-12-15 18:43
こんばんわ。

そもそも、デザイン時にパネルを扱っているのであれば、デザイナを開いた時点で、
既定のコンストラクタが呼ばれています。

NewのときにAddを行なっているということであれば、
デザイナを開きなおすたびにAddが走ることになります。

引用:

Newのタイミングで各Listにデフォルト値をセットしたのですが、
実際に画面に貼り付けた際に、Listにデフォルト値が大量にセットされていました。
どうもデザイナで編集している時に、デフォルト値のAddが走っているような感じなのですが・・・。

Color型のListは増えないのですが、独自クラス型のListは同じデフォルト値が何度かAddされています。
デフォルト値のセットは同じ箇所でやっているので、両方増えるのならばわかるのですが。


先に述べたことから考えると、考えにくい現象ですね。
デザイン時デバッグなどを行なって現象の解明をするほうがいいと思います。

http://msdn.microsoft.com/ja-jp/library/5ytx0z24(VS.80).aspx

※ColorについてはContainsメソッドとかで識別できているけど、(Enumだから)
 独自クラスのインスタンスの場合、Containsではうまく識別できず、
 追加されていくとか考えられそうですね。
KT工房
常連さん
会議室デビュー日: 2006/06/20
投稿数: 49
投稿日時: 2008-12-16 19:00
>Toshiさん

デザイン時デバッグもやってみましたが、原因は解明できていません。
貼り付けたフォームのデザイナが勝手にオブジェクトを生成してAddする処理を
追加しているので、デザイン時デバッグではあまり意味が無かったです(泣)

やりたいことは、独自のクラスなり構造体をリストで管理して
デザイナで追加、編集、削除ができればOKなのですが・・・。

もちろん、変更した内容が保存できるのは当然ですが。

引き続き返答をお待ちしています。
Toshi
ベテラン
会議室デビュー日: 2007/09/18
投稿数: 68
お住まい・勤務地: 関東のどっか
投稿日時: 2008-12-17 11:03
こんにちわ。
何点か。

引用:

パネルを継承したクラスにList型の変数を2つ用意して、
デザイン時にプロパティでリストの内容を編集できるようにしたいのです。


1.これは、こういうことですか??
コード:

Public Class MyPanel
Inherits System.Windows.Forms.Panel
'何かのリスト1
Private list1 As System.Collections.Generic.List(Of Object) = New System.Collections.Generic.List(Of Object)

'何かのリスト2
Private list2 As System.Collections.Generic.List(Of Object) = New System.Collections.Generic.List(Of Object)

// 略

End Class



引用:

Addメソッド自体が、Newにしか記述していないので。
オブジェクト生成の時しか走らないはずなのですが・・・。



2.Addメソッド自体がNewのときにしか記述していないというのはこういうことでしょうか?
コード:

'何かのリスト1
Private list1 As System.Collections.Generic.List(Of Object) = New System.Collections.Generic.List(Of Object)

'何かのリスト2
Private list2 As System.Collections.Generic.List(Of Object) = New System.Collections.Generic.List(Of Object)

Sub New()
'親クラスのコンストラクタを呼ぶ
MyBase.New()
'何かのリストに初期値をいれる
Me.list1.Add("a")
Me.list1.Add("b")
Me.list1.Add("c")

Me.list2.Add("a")
Me.list2.Add("b")
Me.list2.Add("c")
End Sub



現象の再現できる最低限のコードでもない限り、情報が少ないですし、
あてずっぽうな回答になりかねません。
(申し訳ないですが、私の回答は現実としてなっています。)

何を行なっているのか、コードを記載したほうが解決が早いと思われます。


以下、補足
----------------------------------------------------------------------------
先の投稿で申し上げたのは、デザイナを開くと「Sub New()が必ずよばれる。」
ということです。
よって、上記のような記述をしていると、デザイナを開くたびにAddメソッドが走り、予期せぬコレクションの増加につながります。
コンストラクタは情報の初期化につかいますが、デザインタイム中のリストの初期値の格納には適しません。
(たとえばコントロールをFormに配置した直後に、リストに要素を3つ追加するなど)
認識がずれていそうな感じがしましたので、念のため…
----------------------------------------------------------------------------
※初期値の部分を修正しました。
 通常(?)の初期値の格納であれば問題ないです。すいません。


[ メッセージ編集済み 編集者: Toshi 編集日時 2008-12-17 15:06 ]
KT工房
常連さん
会議室デビュー日: 2006/06/20
投稿数: 49
投稿日時: 2008-12-17 13:26
>Toshiさん

返答ありがとうございます。
Toshiさんの記述されているソースに限りなく近いです。

Sub New() で同じようにColorのリストにもAddを行っているのですが、
Colorのリストは増加しないので、余計に悩んでいました。

コード:
--------------------------------------------------------------------------------

'何かのリスト1
Private list1 As System.Collections.Generic.List(Of Object) = New System.Collections.Generic.List(Of Object)

'Colorのリスト2
Private list2 As System.Collections.Generic.List(Of Color) = New System.Collections.Generic.List(Of Color)

Sub New()
'親クラスのコンストラクタを呼ぶ
MyBase.New()
'何かのリストに初期値をいれる
Me.list1.Add("a")
Me.list1.Add("b")
Me.list1.Add("c")

Me.list2.Add(Color.Red)
Me.list2.Add(Color.Yellow)
Me.list2.Add(Color.Blue)
End Sub


--------------------------------------------------------------------------------

上記場合ですと、list1のみ初期値が増加します。
増加するタイミングも判明しまして、デザイナで変更があった場合に増加しているようです。
単純に開いたり、閉じたりでは増えません。
どうも、デザイナが変更を保存する時に初期値のインスタンスの生成とAddメソッドを追記しているようです。

貼り付けたフォームのデザイナを見ると、list1の初期値が増加したぶんだけ生成されAddされているので、当然なのですが・・・。
違いとしては、list2はリソースから取得しているという点だけです。

コンストラクタが初期値の格納に適していないならば、
どこに記述するのが正解なのでしょうか?

Delphiのように標準コントロールのソースを公開してくれていれば、
こんなに悩まずに済みそうなんですけどね。

引き続きよろしくお願いします。
Toshi
ベテラン
会議室デビュー日: 2007/09/18
投稿数: 68
お住まい・勤務地: 関東のどっか
投稿日時: 2008-12-17 15:05
※前回の投稿少し修正しました

おそらく片方のリストだけ項目が増えているのは、
DesignerSerializationVisibilityが片方にしかつけていないからでしょう。

DesignerSerializationVisibilityのついているリストは、デザイナで編集を行なうと、
○○.designer.vbのソースに
------------------
list1.Add(何とか)
------------------
といった記述があるはずです。

一方で、つけていないリストは上記記述がありません。
そのため、おそらくデザイナを閉じると、値が保存されていないかと思います。


KT工房さんが行ないたいのはつぎのようなことなのでしょうか?
・カスタムコントロールに独自のリスト2つを持たせ、利用者にVSのデザイナ上で操作させたい。
・デザイナへカスタムコントロールを追加する時に、初期値として上記リストに項目を追加したい。

※どのようなときに、リストの初期値を追加したいのかが重要です。
 もしデザイン時の動作の拡張をするのであれば、以下のリンク先が参考になるかと思います。
 http://msdn.microsoft.com/ja-jp/library/37899azc(VS.80).aspx

引用:

Delphiのように標準コントロールのソースを公開してくれていれば、
こんなに悩まずに済みそうなんですけどね。



どっかで公開の話なかったでしたっけ・・

※修正しました・・読み返すと誤解与えそうな文章でした・・

[ メッセージ編集済み 編集者: Toshi 編集日時 2008-12-17 15:17 ]

スキルアップ/キャリアアップ(JOB@IT)