System.Windows.Forms.Button class 的 C# 自定义属性

C# Custom Attribute for System.Windows.Forms.Button class

我正在尝试使用几个属性扩展 System.Windows.Forms.Button class。 我想要实现的是有两种不同的颜色,BackColorForeColor,基于 Enabled 属性.

Designer 中的一切看起来都不错, 但是,当我尝试更改颜色时,什么也没有发生。 如果我关闭表单 window 并重新打开它,值将丢失或重置为默认值。

我不知道我错过了什么,但显然我做错了什么或根本没有做。有什么想法吗?

在此先感谢您的帮助

这是我目前用来继承按钮的class:

public partial class ZButton : Button
{
    public ZButton()
    {
        InitializeComponent();
        SetAppearance();
    }

    protected override void OnPaint(PaintEventArgs pe)
    {
        base.OnPaint(pe);
    }

    [Description("The background color of the component"), Category("Appearance"), DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    public new EnableDisableAppearance BackColor { get { return backcolor; } set { backcolor = value; SetAppearance(); } }
    private EnableDisableAppearance backcolor = new EnableDisableAppearance();

    [Description("The text color of the component"), Category("Appearance"), DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    public new EnableDisableAppearance ForeColor { get { return forecolor; } set { forecolor = value; SetAppearance(); } }
    private EnableDisableAppearance forecolor = new EnableDisableAppearance();

    public new bool Enabled { get { return enabled; } set { enabled = value; SetAppearance(); } }
    private bool enabled = true;

    private void SetAppearance()
    {
        base.BackColor = (enabled ? backcolor.Enabled : backcolor.Disabled);
        base.ForeColor = (enabled ? forecolor.Enabled : forecolor.Disabled);
    }
}

这是属性和类型转换器 class:

[TypeConverter(typeof(EnableDisableAppearanceTypeConverter))]
public class EnableDisableAppearance : Attribute
{

    public EnableDisableAppearance()
    {
    }
    public EnableDisableAppearance(Color enabled, Color disabled)
    {
        this.enabled = enabled;
        this.disabled = disabled;
    }

    [Description("Color when enabled"), Category("Appearance"), DesignerSerializationVisibility(DesignerSerializationVisibility.Visible), DefaultValue(typeof(Color), "LightGray")]
    public Color Enabled { get { return enabled; } set { enabled = value; } }
    private Color enabled = new Color();

    [Description("Color when disabled"), Category("Appearance"), DesignerSerializationVisibility(DesignerSerializationVisibility.Visible), DefaultValue(typeof(Color), "DarkGray")]
    public Color Disabled { get { return disabled; } set { disabled = value; } }
    private Color disabled = new Color();

    public override string ToString()
    {
        string ret = "";

        if (enabled.IsKnownColor) { ret += "Enabled " + enabled.ToString(); }
        else { ret += string.Format("Enabled [{0}, {1}, {2}]", enabled.R.ToString(), enabled.G.ToString(), enabled.B.ToString()); }

        if (disabled.IsKnownColor) { ret += ", Disabled " + disabled.ToString(); }
        else { ret += string.Format(", Disabled [{0}, {1}, {2}]", disabled.R.ToString(), disabled.G.ToString(), disabled.B.ToString()); }

        return ret.Replace("Color ", "");
    }

}

public class EnableDisableAppearanceTypeConverter : TypeConverter
{

    public override bool GetPropertiesSupported(ITypeDescriptorContext context)
    {
        return true; //base.GetPropertiesSupported(context);
    }

    public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)
    {
        return TypeDescriptor.GetProperties(typeof(EnableDisableAppearance));
    }
}

EnabledDisabled 属性在 EnableDisableAppearance 中发生更改时,您需要通知 ZButton。为此,添加一个事件并在属性更改时引发它。仅显示附加代码:

public class EnableDisableAppearance : Attribute
{
    public event EventHandler AppearanceChanged;

    protected virtual void OnAppearanceChanged()
    {
        AppearanceChanged?.Invoke(this, EventArgs.Empty);
    }

    [Description("Color when enabled"), ...]
    public Color Enabled
    {
        get { return enabled; }
        set {
            if (value != enabled) {
                enabled = value;
                OnAppearanceChanged();
            }
        }
    }

    // Do the same in the Disabled property...

    ...
}

ZButton必须小心附加和分离事件

public partial class ZButton : Button
{
    private void Backcolor_AppearanceChanged(object sender, EventArgs e)
    {
        SetAppearance();
    }

    [Description("The background color ...]
    public new EnableDisableAppearance BackColor
    {
        get { return backcolor; }
        set {
            if (value != backcolor) {
                if (backcolor != null) {
                    // Detach event handler from old appearance object
                    backcolor.AppearanceChanged -= Backcolor_AppearanceChanged;
                }
                backcolor = value;
                SetAppearance();
                if (backcolor != null) {
                    // Attach event handler to new appearance object
                    backcolor.AppearanceChanged += Backcolor_AppearanceChanged;
                }
            }
        }
    }

    // Same for ForeColor...

    ...
}

为安全添加一些 null 检查

private void SetAppearance()
{
    if (backcolor != null)
        base.BackColor = enabled ? backcolor.Enabled : backcolor.Disabled;
    if (forecolor != null)
        base.ForeColor = enabled ? forecolor.Enabled : forecolor.Disabled;
}