C #: класс Custom Colors, доступный для всех проектов в решении - PullRequest
3 голосов
/ 13 января 2012

У меня есть список пользовательских цветов, которые я использую во всех элементах пользовательского интерфейса моего решения (который содержит несколько проектов).Я мог бы создать статический класс в одном из проектов, в котором я мог бы дать собственные имена своим цветам и затем обращаться к ним в различных точках, но есть ли лучшее решение для нескольких проектов?Можно ли просмотреть эти пользовательские цвета в сетке свойств элементов управления?Например, большинство моих фонов имеют один собственный цвет, и вместо копирования значений RGB я бы хотел иметь возможность выбрать свой собственный цвет.Я понимаю, что могу кодировать его программно, используя класс MyColors, но было бы неплохо, если бы был способ добавить его в таблицу свойств.

Ответы [ 2 ]

9 голосов
/ 13 января 2012

Хорошо, я собирался опубликовать длинный ответ о том, как это невозможно, но потом, после некоторых исследований, я понял, что вы пытаетесь сделать!

Во-первых, использование статического класса для хранения ваших цветов является распространенным и приемлемым способом хранения ваших общих цветов. Вы можете продолжить использовать этот подход.

Вот что нужно сделать, чтобы выставить эти цвета в конструкторе:

  1. Создайте класс CustomColors, который инкапсулирует ваши пользовательские цвета.
  2. Создайте TypeConverter, который может конвертировать между string и CustomColor
  3. Создайте IExtenderProvider, который добавляет CustomForeColor и CustomBackColor ко всем элементам управления в вашей форме.
  4. Везде, где вы хотите использовать свои собственные цвета, вам просто нужно добавить провайдера расширителя в форму (он появится на панели инструментов после компиляции), а затем CustomForeColor и CustomBackColor появятся как виртуальные свойства для всех элементов управления, с хороший выпадающий список.

Вот конечный результат:

enter image description here

Небо - это предел, и если вы хотите, вы можете создать пользовательский UITypeEditor, чтобы фактически закрасить цвет в сетке свойств, но это, вероятно, не обязательно, поскольку вы можете проверять свойства ForeColor и BackColor. Много полезной информации о том, как это сделать, было найдено здесь:

http://msdn.microsoft.com/en-us/library/aa302326.aspx

А вот код:

CustomColor.cs

[TypeConverter(typeof(CustomColorTypeConverter))]
public class CustomColor
{
    public static CustomColor Stop = new CustomColor { Color = Color.Red };
    public static CustomColor Go = new CustomColor { Color = Color.Green };
    public static CustomColor Yield = new CustomColor { Color = Color.Yellow };

    public Color Color { get; private set; }

    internal static CustomColor Find(Color color)
    {
        if (color == CustomColor.Stop.Color)
            return CustomColor.Stop;
        else if (color == CustomColor.Go.Color)
            return CustomColor.Go;
        else if (color == CustomColor.Yield.Color)
            return CustomColor.Yield;

        return new CustomColor { Color = Color.Transparent };
    }
}

CustomColorTypeConverter.cs

public class CustomColorTypeConverter : StringConverter
{
    static Dictionary<CustomColor, string> _nameIndex = InitializeNameIndex();
    static Dictionary<string, CustomColor> _colorIndex = InitializeColorIndex();

    private static Dictionary<string, CustomColor> InitializeColorIndex()
    {
        return typeof(CustomColor)
            .GetFields(BindingFlags.Public | BindingFlags.Static)
            .ToDictionary(f => f.Name, f => (CustomColor)f.GetValue(null));
    }

    private static Dictionary<CustomColor, string> InitializeNameIndex()
    {
        return typeof(CustomColor)
            .GetFields(BindingFlags.Public | BindingFlags.Static)
            .ToDictionary(f => (CustomColor)f.GetValue(null), f => f.Name);
    }

    public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
    {
        return true;
    }

    public override TypeConverter.StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
    {
        return new System.ComponentModel.TypeConverter.StandardValuesCollection(_nameIndex.Values.ToList());
    }

    public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
    {
        if (destinationType == typeof(string))
            return true;

        return base.CanConvertTo(context, destinationType);
    }

    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
    {
        if (sourceType == typeof(CustomColor))
            return true;

        return base.CanConvertFrom(context, sourceType);
    }

    public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
    {
        if (value is string)
        {
            CustomColor result;
            if (_colorIndex.TryGetValue((string)value, out result))
                return result;
            else
                return new CustomColor();
        }

        return base.ConvertFrom(context, culture, value);
    }

    public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
    {
        if (destinationType == typeof(string) && value is CustomColor)
        {
            string result;
            if (_nameIndex.TryGetValue((CustomColor)value, out result))
                return result;
            else
                return String.Empty;
        }
        else
        {
            return base.ConvertTo(context, culture, value, destinationType);
        }
    }
}

CustomColorExtenderProvider.cs

[ProvideProperty("CustomForeColor", typeof(Control))]
[ProvideProperty("CustomBackColor", typeof(Control))]
public class CustomColorExtenderProvider : Component, IExtenderProvider
{
    public CustomColor GetCustomForeColor(Control control)
    {
        return CustomColor.Find(control.ForeColor);
    }

    public CustomColor GetCustomBackColor(Control control)
    {
        return CustomColor.Find(control.BackColor);
    }

    public void SetCustomBackColor(Control control, CustomColor value)
    {
        control.BackColor = value.Color;
    }

    public void SetCustomForeColor(Control control, CustomColor value)
    {
        control.ForeColor = value.Color;
    }

    public bool ShouldSerializeCustomForeColor(Control control)
    {
        return false;
    }

    public bool ShouldSerializeCustomBackColor(Control control)
    {
        return false;
    }

    #region IExtenderProvider Members

    public bool CanExtend(object extendee)
    {
        return (extendee is Control);
    }

    #endregion
}
0 голосов
/ 19 сентября 2018

Я делаю это довольно просто: статический класс определен, например,

public static class GraphicalProperties
{
    public static readonly Color    ControlBackColor    = Color.FromArgb(128, 32, 48);
    public static readonly Color    ControlForeColor    = Color.White;
    public static readonly Font     ControlFont         = new Font("Consolas", 10);
}

Затем в конструкторе каждого элемента управления вы просто добавляете

public MyForm()
{
    InitializeComponent();

    BackColor   = GraphicalProperties.ControlBackColor;
    ForeColor   = GraphicalProperties.ControlForeColor;
    Font        = GraphicalProperties.ControlFont;
}

Это обеспечивает небольшую автоматизацию и отсутствие записей в таблице свойств, но очень просто и, на мой взгляд, практически.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...