【问题标题】:Prevent Winforms Designer from Generating Property Values for Inherited Controls防止 Winforms Designer 为继承的控件生成属性值
【发布时间】:2014-01-17 03:51:20
【问题描述】:

我有一个自定义的DataGridView,比如说:

public MyGridView : DataGridView
{
    public MyGridView()
    {
         BackgroundColor = Color.Red;
    }
}

现在,当我在使用设计器的项目中使用此控件时,出于某种原因,我觉得还需要在 Designer.cs 文件中设置属性。

所以在设计器文件中,我会:

this.MyGridView1.BackgroundColor = System.Drawing.Color.FromArgb((byte)(int)255, (byte)(int)0, (byte)(int)0);

我遇到的问题是,它使我无法在 MyGridView 的构造函数中更改颜色,而不必遍历我用来控制和更改每个实例的所有表单,渲染我的自定义控件没用。

对于一些提供虚拟吸气剂的属性,这没问题,但大多数属性没有它。

如何防止设计者生成此代码?

【问题讨论】:

  • 使用DefaultValue 属性装饰属性。
  • @NikolaMarkovinović 这些不是我创建的属性,这些是继承自DataGridView 的属性(例如BackgroundColor)。我应该在哪里添加属性?
  • 对我没有通读问题很有帮助。我认为没有可接受的解决方案。您可以像 this answer 处理继承的 ComboBox 那样隐藏原始属性。再次道歉。
  • @NikolaMarkovinović 没问题!至少你给了它一些关注:) 你链接的问题是一个可能的解决方法,但它只适用于constable 值。有没有办法将默认值属性分配给非constable 值类型?

标签: c# .net winforms visual-studio-2010 windows-forms-designer


【解决方案1】:

我要强调的是,这通常不是你这样做的方式,[DefaultValue] 属性通常是正确的选择。但是您正在使用 Color 类型的属性,以灵活的方式为其编写属性并不简单。您可以传递给属性构造函数的参数只能是少数几种数据类型,颜色不是其中之一。您必须制作一个 ColorConverter 可以理解的 字符串,这既丑陋又难以维护。

PropertyGrid 具有为“困难”属性提供默认值的第二种方式,它还会在类中查找特别命名的私有成员。给定一个名为“Xxxx”的属性,它会查找以下内容:

  • DefaultXxxx,只有一个返回默认值的 getter 的属性
  • ResetXxxx(),当用户选择重置上下文菜单项时可以运行的方法
  • ShouldSerializeXxxx(),如果该属性的值不应被持久化,则该方法应返回 false

这使得这段代码可以工作:

public class MyGridView : DataGridView {
    public MyGridView() {
        this.BackgroundColor = DefaultBackgroundColor;
    }
    public new Color BackgroundColor {
        get { return base.BackgroundColor; }
        set { base.BackgroundColor = value;  }
    }
    private bool ShouldSerializeBackgroundColor() {
        return !this.BackgroundColor.Equals(DefaultBackgroundColor);
    }
    private void ResetBackgroundColor() {
        this.BackgroundColor = DefaultBackgroundColor;
    }
    private static Color DefaultBackgroundColor {
        get { return Color.Red; }
    }
}

请注意,ResetBackgroundColor() 方法实际上并不是必需的,因为当用户重置属性时不需要特殊效果,我只是为了完整性而包含它。

【讨论】:

  • 对于像 AlternatingRowsDefaultCellStyle.BackColor 属性这样更深层次的东西,你会如何做呢?
  • 这种方法适用于任何颜色类型的属性,BackgroundColor 只是一个例子。更改 DataGridView.AlternatingRowsDefaultCellStyle 属性需要做更多的工作,因为您不仅需要更改颜色,还必须提供 DataGridViewCellStyle 实例。点击按钮获取帮助。
  • ResetXxxx()ShouldSerializeXxxx() 方法记录在 here。有人找到DefaultXxxx 属性机制的官方文档了吗?
【解决方案2】:

有一种更简单的方法可以将 DefaultValue 分配给 Color:

public class MyGridView : DataGridView
{
    public MyGridView()
    {
        BackgroundColor = Color.Red;
    }

    [DefaultValue(typeof(Color), "Red")]
    public new Color BackgroundColor
    {
        get { return base.BackgroundColor; }
        set { base.BackgroundColor = value; }
    }
}

【讨论】:

    【解决方案3】:

    尝试改用 InitLayout 和 DesignMode。您不能在 ctor 中使用 DesignMode,但在构造控件后,您可以正确访问 Designmode 属性以设置颜色。注意:这不会在设计器中设置样式,只是在运行时。

    public class MyGridView : DataGridView
    {
    
        protected override void InitLayout()
        {
            base.InitLayout();
    
            if (!DesignMode)
                BackgroundColor = Color.Red;
        }
    }
    

    【讨论】:

    • 谢谢,这是一个合理的妥协。由于特定于我的项目的原因,我在 OnHandleCreated 方法中使用它。
    【解决方案4】:

    如果需求简单且外观设计没问题,请尝试编写一两个扩展,例如,

    public static class Extensions
    {
        public static void ApplyStyle( this DataGridView dataGridView )
        {
            dataGridView.RowHeadersVisible = false;
            ...
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-01-28
      • 2012-09-29
      • 2021-07-19
      • 1970-01-01
      • 2014-10-08
      • 2010-09-05
      • 1970-01-01
      • 2021-10-03
      相关资源
      最近更新 更多