Я ищу способ настроить собственные значения свойств по умолчанию для различных типов элементов управления в моем приложении Windows на C # .NET. Значения свойств по умолчанию должны «переопределять» существующие значения по умолчанию для элементов управления, но при этом должны быть «переопределены», если явно установить значения свойств в конструкторе.
Это должно упростить процесс изменения внешнего вида / поведения элементов управления по умолчанию, когда клиент (или я) передумал в 10-й раз. Это особенно относится к элементам управления, таким как DataGridView
или сторонним элементам управления, где необходимо сохранить множество свойств, связанных с макетом.
Мне известна возможность создавать унаследованные элементы управления и использовать атрибут DefaultValue
, но это не решение, которое я ищу по нескольким причинам:
- Это проблема, связанная с наследованием каждого типа элемента управления, для которого я хочу указать пользовательские свойства, не говоря уже о переопределении / затенении свойств и установке атрибута DefaultValue.
- Я больше не могу использовать стандартные элементы управления .NET, но вынужден использовать унаследованные элементы управления.
- Количество унаследованных элементов управления со временем увеличивается и загромождает набор инструментов.
- Я или другие разработчики проекта забываем использовать новые унаследованные типы во время поспешности, что приводит к неосторожному поведению / появлению элементов управления.
Вот как я представлял, что это будет работать:
Пример 1: A DataGridView
по умолчанию имеет цвет фона
SystemColors.Window
. Я установил свой собственный
значение по умолчанию Color.Blue
(как
возмутительно!). В дизайнере
используется цвет фона по умолчанию,
т.е. цвет фона не установлен
явно в файле .designer.cs.
При запуске приложения часть кода выполняется, что приводит к повороту сетки
синий, как указано мной.
Пример 2: Для того же цвета фона DataGridView
установлено значение
Color.Red
в конструкторе. это
переопределяет мое собственное значение по умолчанию синего цвета, показывая красный фон
в сетке, как во время разработки, так и во время выполнения.
Решение
Решением для меня было использование отражения для проверки атрибута 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);
}
}