[英]Application-wide control defaults
我正在尋找一種在C#.NET Windows應用程序中為不同類型的控件設置自己的默認屬性值的方法。 默認屬性值應“覆蓋”控件的現有默認值,但仍可以通過在設計器中顯式設置屬性值來“覆蓋”。
這是為了簡化客戶端(或我本人)第十次改變主意時更改默認外觀/控件行為的過程。 這尤其涉及到諸如DataGridView
或第3方控件之類的控件,其中需要維護大量與布局相關的屬性。
我知道創建繼承的控件並使用DefaultValue
屬性的能力,但這不是我正在尋找的解決方案 ,原因有兩個:
這是我想象的它將起作用的方式:
示例1:默認情況下, DataGridView
的背景色為SystemColors.Window
。 我將自己的默認值設置為Color.Blue
( Color.Blue
離譜了!)。 在設計器中,使用默認的背景色,即未在.designer.cs文件中明確設置背景色。 運行應用程序時,將執行一部分代碼,從而使網格變成藍色,這是我指定的。
示例2:在設計器中,同一DataGridView
的背景色設置為Color.Red
。 這將覆蓋我自己的默認值blue,即在設計時和運行時都在網格中顯示紅色背景。
對我來說,解決方案是使用反射來檢查DefaultValue
屬性,所建議丹尼爾·布魯克納 。
我遍歷窗體上的所有控件,為每個控件調用SetDefaultValues
。 對於每個要設置的屬性值,我調用SetValue
方法,該方法確保僅設置未更改其默認值的屬性。
但是,這種方法有一個缺陷 。 在設計器中已明確設置但與默認值沒有區別的屬性將被SetValue
方法覆蓋。
void SetDefaultValues(Control control)
{
if (control is DataGridView)
{
SetValue(control, "BackColor", Color.Blue);
}
else if (control is TextBox)
{
// etc.
}
}
private static void SetValue(object control, string propertyName, object newValue)
{
System.Reflection.PropertyInfo prop = control.GetType().GetProperty(propertyName);
if (prop == null)
{
throw new ArgumentException(string.Format(
"Specified property \"{0}\" does not exist on type \"{1}\".", prop.Name, control.GetType().FullName),
"propertyName");
}
bool defaultValueFound = false;
object defaultValue = null;
foreach (object attr in prop.GetCustomAttributes(true))
{
if (attr is DefaultValueAttribute)
{
defaultValue = ((DefaultValueAttribute)attr).Value;
defaultValueFound = true;
break;
}
}
if (!defaultValueFound && prop.PropertyType.IsValueType)
{
// Get default value for value types if no default value was specified by attributes:
defaultValue = Activator.CreateInstance(prop.PropertyType);
}
if (defaultValue == null || defaultValue.Equals(prop.GetValue(control, null)))
{
// If default value matches current value, set new value:
prop.SetValue(control, newValue, null);
}
}
雖然不如泛型那么漂亮,但您也許可以通過Control Builders進行一些操作以實現這一目標。
編輯:
昨晚,我使用ControlBuilder對通用包裝控件進行了快速原型設計。 我對結果不滿意。 雖然您可能可以使它工作,但我相信一個新的Page或Container類可能會更簡單。 我在測試中使用的源代碼可在我的博客上找到 。
我已經使用或可以想到幾種解決方案。
您可以改為覆蓋頁面,並循環瀏覽所有控件,例如
foreach (Control c in Page.Controls)
{
if (c is Textbox)
{
(Textbox)c.Color.blah.blah.blah ;)
}
///etc
Recurse through (c.Controls);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.