- - PR -
ユーザーコントロールのプロパティ自動設定
投稿者 | 投稿内容 | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2006-05-29 16:25
VB2005でユーザーコントロールの設計として例えば以下のようになっているものとします。
要約しますとAPropとBPropの2つのプロパティがあり、BPropに負の値がセットされた場合にはAPropに1をセットすることが多いためBPropのセット時にAPropへ1を自動セットする、といった感じです。 APropとBPropは厳密な関連性があるわけではなく、このコントロールを使用するユーザーの利便性を考慮して自動セットしたいだけなので、先にBPropに負の値をセットして自動的にAPropが1になってから、手動でAPropの値を変えてもよいという風にしたいと思っています。 DateTimePickerでCustomFormatが入力されたら自動でFormatプロパティをCustomにするようなイメージと言った方がわかりやすいでしょうか? あるいはVB6時代のFormもBorderStyleを既定の「2 - 可変」から「1 - 固定(実線)」などに変更するとMaxButtonやMinButtonが自動でFalseになりますが、MinButtonだけTrueに戻すことも可能でしたよね?そんな感じです。 APropとBPropの名前が逆転(APropの値に応じてBPropを初期化する)していれば希望通りの動作をしてくれるのですが、デザイナが自動生成するInitializeComponent内のコードは下記のようにアルファベット順(?)でプロパティを設定するようなのでいったんAPropに手動設定した値がセットされるものの直後のBProp設定によって初期化される、という風になってしまいます。
デザイナが自動生成するプロパティ設定の順番を操作できるような属性がないか探したのですがそれらしいものが見つかりませんでした。 これを実現する何かよい方法がありましたら教えてください。 | ||||||||||||
|
投稿日時: 2006-05-29 23:27
ちょっとややこしくて、僕も混乱しているのですが。
要するに、あるプロパティをデザイナでセットしたら、これに関連して他のプロパティの値が自動的に切り替わる。しかし、その後、直接プロパティの値を変更することもできると理解しました。 プロパティの記述される順番を変える方法は僕もわからないのですが。 良い方法というよりは、細工方法として似たような処理を作ったことがあります。 それは、初期値(0やnull)を指定しておいて、その場合は、元となるプロパティの値から一定の規則に従った値が指定されているものと同じ動作をするというものです。 値が指定されていれば、その値に従った処理をします。 | ||||||||||||
|
投稿日時: 2006-05-30 13:08
ご回答ありがとうございます。
ご理解いただいた通りです。なかなかうまく説明できなくてすみません。 具体的に作ろうとしていたのはこれもよくあると思うのですが数値のみ入力可能なTextBoxを継承したコントロールで拡張プロパティとしてTypeとDisplayFormat、Min/MaxValueといったプロパティなどを追加してあります。 (前回のファンクションキーコントロールに続いてこれもInputManではNumberコントロールとして存在するものの簡易版です(笑)) Typeは入力制限に関するプロパティで整数型(数値と+-,のみ入力可)と小数型(さらに.を入力可)を選択でき、DisplayFormatはLeaveイベントで自動フォーマットされる書式を設定できるという設計にしました。 整数型の場合は"#,##0"、小数型の場合は"#,##0.0"であることがほとんどなのでTypeプロパティを変更した際に自動でこれをDisplayFormatに設定し、やっぱりカンマはいらないとか小数部2桁にしたい、といった場合にはDisplayFormatを書き換えればよいというものです。 このためInitializeComponent内ではアルファベット順的にDisplayFormatがまず設定されてからTypeが設定され、DisplayFormatが初期化されてしまうという現象になっておりました。 その後も色々探していてDesignModeというプロパティがあるのを知り
というように条件に加えてみたところ、InitializeComponentの例の部分が処理されるタイミングではDesignModeがFalseなので_APropが自動初期化されないようになり、うまくいったかのように見えたのですが…。 このユーザーコントロールを配置したデバッグ用フォームを起動・終了させてデザイナ画面に戻ってくると、プロパティグリッドでは自動で切り替わった値が表示(AProp=1, BProp=-1)され、しかしInitializeComponent内はAProp=5、BProp=-1と手動で設定した内容が保たれており、同期のとれていないおかしな状態になってしまいました。
上記の具体例ですとDisplayFormatが空だった場合にはTypeに応じた書式が自動で使われる仕組みにする、ということですね。 ただ、そうしますとDisplayFormatを空にしたい(自動フォーマットしなくてよい)場合に困ってしまいます。 (自動フォーマットするかどうか、というプロパティをさらに追加すればいいことなんでしょうけど…) また、仮に自動設定されるプロパティとしてBoolean型のものを追加したとすると、プロパティグリッド上ではFalseとなっているのに実行時・内部的には勝手にTrueとして扱われるというようなことになり、空かそうでないかといった見た目に比べてかなり違和感がありそうな気がします。 最初の投稿で挙げたようにVB6のFormではBorderStyleを変えることでMax/MinButtonがFalseになったりしていましたが、VB2005ではFormBorderStyleをFixedSingleなどに変えてもMaximize/MinimizeBoxがFalseになったりしてくれないようなので、あまりやらないものなのでしょうか…? 設定を忘れてタイトルバーをダブルクリックしたらショボいウィンドウになったり…しません?(笑) | ||||||||||||
|
投稿日時: 2006-05-30 14:44
質問の意味を理解できていないかもしれませんが、
ISupportInitialize インターフェイスが必要ということでしょうか? _________________ C# と VB.NET の入門サイト じゃんぬねっと日誌 | ||||||||||||
|
投稿日時: 2006-05-30 18:43
ご回答ありがとうございます。
すみません、ISupportInitializeをキーワードに検索してみたのですがどのように使えばよいのかよくわかりませんでした。 以前にじゃんぬねっと様のホームページからExTextBoxをDLして試用させていただいたことがあったのですが、都合により使用が許可されなかったので自分で簡易版を作っているところです(泣) あのExTextBoxでもAvailableTypeをIntやValueに設定した時点で自動的にFormatを設定してくれる設計になっていましたよね? 私もそれを真似て「AvailableType」「Format」というアルファベット順のプロパティ名にしておけばよかった(?)のに「DisplayFormat」「Type」としてしまったせいで苦労しております。 ExTextBoxではAvailableTypeよりもアルファベット順的に前になるプロパティがなかったと思いますが、もしあった場合に私が遭遇しているような現象を回避するような処理が何か組み込まれていましたらその方法を教えていただけるとうれしいです。 | ||||||||||||
|
投稿日時: 2006-06-04 21:49
返事が遅くなりました。(*_ _)
今、これを見たら、何となくわかったような気がします。 思いつきですが、以下のようにされてはいかがでしょう。 UserControl1 クラスに bool 型の initializeFlag というプライベート メンバを持つ。 OnHandleCreated メソッドをオーバーライドして、このフラグを true にする。 (基底クラスの OnHandleCreated メソッドの呼び出しは、最初に行う) BProp プロパティの Setter で、セットしようとする値と現在の値が、同じ値の場合は無視するようにする。 # 他のプロパティも、そうしておくことが望ましいです。 # 将来、[プロパティ名] + Changed イベントが実装されるかもしれませんから。 セットしようとする値と、現在の値が違う値の場合は、まず、プロパティ変数 (実体) に値をセットする。 その後、DesignMode でない場合かつ、ハンドルが生成されていない場合は、 条件による (value < 0 の時の) AProp への値の強制設定 (AProp = 1) は行わない。
関係のないところですが、RefreshProperties 属性の値は Repaint で良いです。 _________________ C# と VB.NET の入門サイト じゃんぬねっと日誌 | ||||||||||||
|
投稿日時: 2006-06-05 16:53
じゃんぬねっとさん、ご回答ありがとうございます。
前回ファンクションキーコントロールに関する質問で教えていただいたように、ここでもOnHandleCreatedが判断材料として使えたのですね。 早速、以下のように修正してみたところ、デザイン時以外では初期化されないようになりました。
| ||||||||||||
|
投稿日時: 2006-06-05 17:29
解決できたようで良かったです。 細かいところですが、Changed イベントの実装位置は、_BProp = value 直後が望ましいです。
今の実装で APropChanged イベントが追加された場合、 BProp の変更によって AProp が変更された時に、 APropChanged イベントが BPropChanged イベントより先に発生するからです。 _________________ C# と VB.NET の入門サイト じゃんぬねっと日誌 |