自定义表单属性值在运行时保持重置

时间:2014-11-16 16:19:40

标签: c# forms themes

我有一个自定义表单,它扩展了Form,它覆盖了OnPaint方法,使用Theme在特定设计中绘制表单。我有一个自定义课程"主题"其中包含要在表单上设置的四种颜色:

public class Theme
{
    public Color BackColor { get; set; }
    public Color MouseHoverColor { get; set; }
    public Color ThemeColor { get; set; }
    public Color ForeColor { get; set; }
}

主题有一个自定义的UITypeEditor,它使用了一个使用颜色选择器的自定义主题编辑器,我已经测试并且工作正常:

public class ThemeTypeEditor : UITypeEditor
{
    public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
    {
        return UITypeEditorEditStyle.Modal;
    }

    public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
    {
        var editor = new ThemeEditor((CustomForm) context.Instance);

        if (editor.ShowDialog() == DialogResult.OK)
        {
            return editor.Theme;
        }

        return base.EditValue(context, provider, value);
    }
}

我还有一个静态类"主题"其中包含要使用的表单的默认主题:

public static class Themes
{
    public static Theme DarkGreen = new Theme
    {
        BackColor = Color.FromArgb(53, 53, 53),
        ForeColor = Color.FromArgb(237, 234, 235),
        MouseHoverColor = Color.FromArgb(65,65,65),
        ThemeColor = Color.FromArgb(32, 203, 88)
    };
}

在我的自定义表单中,我有一个OnPaint方法使用的属性:

private Theme theme = (Theme) Themes.DarkGreen;
[Category("Appearance"),
 Description("Specifies the Theme for this form."),
Editor(typeof(ThemeTypeEditor), typeof(UITypeEditor)),
DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public Theme Theme {
    get { return theme; }
    set {
        theme = value;
        Invalidate();
    }
}

但是,当我尝试在扩展CustomForm的新表单上更改设计器中的主题时,设计器不会更新,主题会在运行时恢复为Themes.DarkGreen。我不确定我应该为此做些什么,因为我的理解是我应该能够改变主题并在设计时和运行时看到变化。如上所述,OnPaint方法使用上面的Theme字段绘制表单的背景颜色和其他绘制的图形。任何帮助表示赞赏。

修改

表单设计器中的表单在构建和运行项目时会更改,但实际运行的表单保持不变。我希望在应用主题时立即看到更改,并将其应用于构建的应用程序。

编辑2:

我决定展示一个MessageBox来调试它。在我返回新主题之前,我在ThemeTypeEditor的EditValue方法中放置了一个,当然,它有效,并且主题值是正确的。但是,在Invalidate();之后,我还在我的主题属性设置器中放置了一个MessageBox,并且没有显示任何内容。就像财产的集合根本没有被调用一样。

1 个答案:

答案 0 :(得分:0)

我通过改变各种事情来解决这个问题。第一个是创建一个名为ComponentBase的基类,它扩展了Component并实现了INotifyPropertyChanged:

public class ComponentBase : Component, INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator]
    private void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        var handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }

    protected bool SetField<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
    {
        if (EqualityComparer<T>.Default.Equals(field, value)) return false;

        var changeService = GetService(typeof(IComponentChangeService)) as IComponentChangeService;
        if (changeService != null)
            changeService.OnComponentChanged(this, TypeDescriptor.GetProperties(this).Find(propertyName, false), field, value);

        field = value;
        OnPropertyChanged(propertyName);

        return true;
    }
}

这意味着我需要删除主题属性的自动属性。我更改了主题中每个颜色的编辑器,以便它使用颜色选择器,并为它们提供了Visible的DesignerSerializationVisibility:

public sealed partial class Theme : ComponentBase
{
    private Color backgroundColor;

    [Category("Theme")]
    [DisplayName("Background Color")]
    [Editor(typeof (ThemeTypeEditor), typeof (UITypeEditor))]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
    [TypeConverter(typeof (ThemeColorConverter))]
    public Color BackgroundColor
    {
        get { return backgroundColor; }
        set { SetField(ref backgroundColor, value); }
    }

    private Color foregroundColor;

    [Category("Theme")]
    [DisplayName("Foreground Color")]
    [Editor(typeof(ThemeTypeEditor), typeof(UITypeEditor))]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
    [TypeConverter(typeof(ThemeColorConverter))]
    public Color ForegroundColor
    {
        get { return foregroundColor; }
        set { SetField(ref foregroundColor, value); }
    }

    private Color highlightColor;

    [Category("Theme")]
    [DisplayName("Highlight Color")]
    [Editor(typeof(ThemeTypeEditor), typeof(UITypeEditor))]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
    [TypeConverter(typeof(ThemeColorConverter))]
    public Color HighlightColor
    {
        get { return highlightColor; }
        set { SetField(ref highlightColor, value); }
    }

    private Color borderColor;

    [Category("Theme")]
    [DisplayName("Border Color")]
    [Editor(typeof(ThemeTypeEditor), typeof(UITypeEditor))]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
    [TypeConverter(typeof(ThemeColorConverter))]
    public Color BorderColor
    {
        get { return borderColor; }
        set { SetField(ref borderColor, value); }
    }

    private Color themeColor;

    [Category("Theme")]
    [DisplayName("Theme Color")]
    [Editor(typeof(ThemeTypeEditor), typeof(UITypeEditor))]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
    [TypeConverter(typeof(ThemeColorConverter))]
    public Color ThemeColor
    {
        get { return themeColor; }
        set { SetField(ref themeColor, value); }
    }
}

由于我的自定义表单中的主题使用DesignerSerializationVisibility.Content,因此可以为主题的内容生成代码,这意味着主题中的各个颜色在设计时和运行时都会更新:

private Theme theme;

[DisplayName("Theme")]
[Category("Appearance")]
[Description("Specifies the Theme for this form.")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public Theme Theme
{
    get { return theme; }
    set
    {
        theme = value;
        Invalidate();
    }
}