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

时间:2017-11-08 15:20:58

标签: c# winforms nested attributes custom-attributes

我正在尝试使用几个属性扩展 System.Windows.Forms.Button 类。 我想要实现的是基于启用属性,为 BackColor ForeColor 设置两种不同的颜色。

设计师的一切看起来都不错, 但是,当我尝试改变颜色时,没有任何反应。 如果我关闭表单窗口并重新打开它,则值将丢失或重置为默认值。

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

提前感谢您的帮助

这是我目前用来继承Button的类:

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);
    }
}

这是Attribute和TypeConverter类:

[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));
    }
}

1 个答案:

答案 0 :(得分:1)

ZButtonEnabledDisabled属性发生变化时,您需要通知EnableDisableAppearance。为此,添加一个事件并在属性更改时将其引发。仅显示其他代码:

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...

    ...
}

添加一些空检查以确保安全

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