トップ回答者
TextBoxのBackColorの既定値の制御と同じ実装

質問
-
Visual Studo 2017
.Net Framework 4.5
Windowsフォームアプリケーションいじってたら初めて知ったんですが、TextBoxのBackColorの既定値って、ReadOnly=falseだとWindowなのに、ReadOnly=trueにした途端、Controlになっていました。
(ReadOnlyを変えたらBackColorが自動的に変わるという意味ではなく、既定値)つまり、ReadOnlyの状態によってBackColorの既定値が都度変化しています。
これと同じ実装は独自コントロールでも実現できるものなのでしょうか?
DefaultValueAttributeでは出来なそうですが。
回答
-
別にReadOnlyプロパティに応じでBackColorプロパティが返す値を変化させるだけでは?
private Color DefaultBackColor => ReadOnly ? SystemColors.Window : SystemColors.Control; Color? backColor; public Color BackColor { get => backColor ?? DefaultBackColor; set => backColor = value; } internal bool ShouldSerializeBackColor() => backColor != null && backColor != DefaultBackColor; internal void ResetBackColor() => backColor = null;
ReadOnlyプロパティの値に応じて決定されるDefaultBackColorプロパティ、BackColorプロパティのバッキングストアであり、未設定状態を持つbackColorフィールドを用意します。BackColorプロパティはbackColorバッキングストアが値を持っていればそれを、持っていなければDefaultBackColorを返します。デザイナがBackColorプロパティをシリアライズすべきかどうかを判定するShouldSerializeBackColor()は値が変更されているかで判断します。リセット実行時の動作をResetBackColor()メソッドで指定できます。
この機能はShouldSerialize メソッドと Reset メソッドによる既定値の定義で説明されています。
- 編集済み 佐祐理 2017年4月11日 8:49 Resetメソッドの追加
- 回答の候補に設定 Tak1waMVP, Moderator 2017年4月11日 12:38
- 回答としてマーク takiru 2017年4月12日 8:32
すべての返信
-
別にReadOnlyプロパティに応じでBackColorプロパティが返す値を変化させるだけでは?
private Color DefaultBackColor => ReadOnly ? SystemColors.Window : SystemColors.Control; Color? backColor; public Color BackColor { get => backColor ?? DefaultBackColor; set => backColor = value; } internal bool ShouldSerializeBackColor() => backColor != null && backColor != DefaultBackColor; internal void ResetBackColor() => backColor = null;
ReadOnlyプロパティの値に応じて決定されるDefaultBackColorプロパティ、BackColorプロパティのバッキングストアであり、未設定状態を持つbackColorフィールドを用意します。BackColorプロパティはbackColorバッキングストアが値を持っていればそれを、持っていなければDefaultBackColorを返します。デザイナがBackColorプロパティをシリアライズすべきかどうかを判定するShouldSerializeBackColor()は値が変更されているかで判断します。リセット実行時の動作をResetBackColor()メソッドで指定できます。
この機能はShouldSerialize メソッドと Reset メソッドによる既定値の定義で説明されています。
- 編集済み 佐祐理 2017年4月11日 8:49 Resetメソッドの追加
- 回答の候補に設定 Tak1waMVP, Moderator 2017年4月11日 12:38
- 回答としてマーク takiru 2017年4月12日 8:32
-
ご回答ありがとうございます。
教えていただいた方法で、BackColor2なるものを作ってみました。ReadOnlyプロパティに応じて色が切り替わることが確認できましたが、デザイナ上でBackColor2プロパティを右クリックしてリセットを選択した際、ReadOnlyプロパティの状態に応じた既定値に戻す、ということが実現できません。
using System.ComponentModel; using System.Drawing; using System.Windows.Forms; namespace WindowsFormsApp1 { public class ExTextBox : TextBox { private new Color DefaultBackColor => ReadOnly ? Color.Red : Color.Blue; Color? backColor; [Browsable(true)] public Color BackColor2 { get => this.backColor ?? this.DefaultBackColor; set { this.backColor = value; } } internal bool ShouldSerializeBackColor() { return this.backColor != null && this.backColor != this.DefaultBackColor; } } }
-
できました!ありがとうございます!!
ShouldSerialize メソッドと Reset メソッドによる既定値の定義は初めて知りました。
任意のプロパティ名を連結して、状態を管理・操作できるんですね。
いろいろいじってみた結果、上記ページにも書いてありますが、以下のことが確認できました。
・プロパティ値が変更されていない時に、プロパティ値が太字にならない。(ShouldSerializeXXX()の役割)
・既定値のリセットが行える。(ResetXXX()の役割)実行時にボタン起因などでReadOnlyプロパティが変更された時に、リアルタイムに背景色が変わらなかったので(フォーカスがあたると色が変わった)、プロパティのGetterでRefresh()することで解決しました。
using System.ComponentModel; using System.Drawing; using System.Windows.Forms; namespace WindowsFormsApp1 { class ExTextBox : TextBox { private Color DefaultBackColor2 => ReadOnly ? Color.Red : Color.Blue; Color? backColor2; [Browsable(true)] public Color BackColor2 { get { this.Refresh(); this.backColor2 ?? this.DefaultBackColor2; } set =>this.backColor2 = value; } internal bool ShouldSerializeBackColor2() => this.backColor2 != null && this.backColor2 != this.DefaultBackColor2; internal void ResetBackColor2() => this.backColor2 = null; } }
- 編集済み takiru 2017年4月11日 10:13