【问题标题】:How to tell if a WinForms control's property is the "default" value?如何判断 WinForms 控件的属性是否为“默认”值?
【发布时间】:2012-01-05 07:24:01
【问题描述】:

如何判断 WinForms Control属性 是否为“默认”值?

注意:在设计时,当属性变为粗体时,您可以判断该属性不再是“默认”。

这是一个标签字体的示例(在设计时),它是 “默认”值(这意味着它从其父级获取其值):

(如果父字体改变,这个标签的字体也会改变)

这里一个标签的字体已经改变,不再是默认值:

(如果父字体改变,这个标签的字体不会改变)

细心的观察者会注意到,同一面板上的这两个标签是“相同的字体”;除了一个是默认而另一个不是

注意:我需要在 runtime 知道某个属性是否不是“默认”值。 (有人可能会作弊说,“查看属性窗口。如果属性是粗体,你就知道它不再是默认值了”。)

注意:注意,我的问题不仅限于标签字体 - 这只是我使用的示例。我可能想知道它是否仍然是默认值的其他属性示例:

  • ForeColor
  • BackColor
  • ToolStrip.ImageScalingSize
  • SplitContainer.FixedPanel

我陷入疯狂的尝试

我将把这些失败的随机乱码呕吐尝试留在这里:

internal static Boolean GetIsPropertyDefault(object o, string propertyName)
{
    return false;

/*  Debug.WriteLine(String.Format("GetIsPropertyDefault: {0}.{1} = {2}", o, propertyName, TypeDescriptor.GetProperties(o)[propertyName].GetValue(o)));

    // Gets the attributes for the property.
    AttributeCollection attributes = TypeDescriptor.GetProperties(o)[propertyName].Attributes;

    DefaultValueAttribute myAttribute = (DefaultValueAttribute)attributes[typeof(DefaultValueAttribute)];

    Debug.WriteLine(String.Format("The default value is: {0}", myAttribute));

    if (myAttribute == null)
        return true;

    return (TypeDescriptor.GetProperties(o)[propertyName].GetValue(o) == myAttribute.Value);
*/

//          return (myAttribute.Value == null);



//          Console.WriteLine("The default value is: " + myAttribute.Value.ToString());

/*  System.Reflection.PropertyInfo pi;
    try
    {           
        //pi = o.GetType().GetProperty(propertyName).GetCustomAttributes(typeof(DefaultAttribute), false).
    }
    catch
    {
        return true;
    }
    if (pi == null) 
        return true;

    System.Diagnostics.Trace.TraceInformation(pi.Attributes.ToString());
    */

//          return false;
/*          foreach (Attribute attr in pi.Attributes)
    {
        if (attr is System.ComponentModel.DefaultValueAttribute)
        {
            System.ComponentModel.DefaultValueAttribute dv = (System.ComponentModel.DefaultValueAttribute)attr;

        }
    }
*/
}

【问题讨论】:

标签: winforms properties controls


【解决方案1】:

通过反射,您可以检查DefaultValue 属性的属性。 PropertyGrid 使用它来确定哪些应该加粗,哪些不应该加粗。

要查找的“其他”属性是AmbientValueAttribute

当我这样做时:

List<string> list = new List<string>();
Attribute[] attrs = Attribute.GetCustomAttributes(typeof(Label).GetProperty("Font"));
foreach (Attribute att in attrs) {
  list.Add(att.ToString());
}

我得到了以下属性:

  • System.ComponentModel.AmbientValueAttribute
  • System.Runtime.InteropServices.DispIdAttribute
  • System.Windows.Forms.SRCategoryAttribute
  • System.ComponentModel.LocalizableAttribute
  • System.Windows.Forms.SRDescriptionAttribute

来自AmbientValueAttribute Class

如果控件上的属性具有环境行为,则该属性必须存在。环境属性查询其父级的值,例如 Control.Font 属性或 Control.BackColor 属性。

通常,视觉设计者使用 AmbientValueAttribute 特性来决定为属性保留哪个值。这通常是导致属性从另一个来源获取其值的值。环境值的一个示例是 Color.Empty 作为 BackColor 属性的环境值。如果您在窗体上有一个控件,并且控件的 BackColor 属性设置为与窗体的 BackColor 属性不同的颜色,则可以通过设置控件的 BackColor 将控件的 BackColor 属性重置为窗体的颜色到 Color.Empty。

可能不会让您尝试做的事情变得更容易,因为 AmbientValue 基本上告诉类查看它的父级。对于像“字体”这样的属性,你可以调用静态函数 DefaultFont:

MessageBox.Show(Label.DefaultFont.ToString());

在我的系统上,结果:

[字体:名称=Microsoft Sans Serif,大小=8.25,单位=3,GdiCharSet=0,GdiVerticalFont=False]

【讨论】:

  • label1.GetType().GetProperty("Font").Attributes 包含None。也许一些代码来解释你将如何完成它。
  • 还有另一种机制,一个类可以包含一个 ShouldSerializeXxxx() 方法,其中 Xxxx 是属性名称。这是用于 Font 属性的内容。需要反射,它是一种内部方法。简单明了的方法是将属性值与父级的值进行比较。
  • @HansPassant 它不能太内部,如果属性窗口能够确定控件的属性是否不再是“它应该是什么”
  • PropertyGrid 使用反射。反射可以访问内部和私有成员。
  • 环境属性可能会告诉某人他们可以查看父级(这可能是使用的机制,而不是“默认”值)。但我不必(在 Label.Font 的情况下)使用Label.DefaultFont,因为我可以只查询Label.Font。但问题仍然存在,我怎么知道Label.Font 是否是“非粗体值”
猜你喜欢
  • 2014-09-02
  • 2016-04-27
  • 2012-10-03
  • 1970-01-01
  • 1970-01-01
  • 2011-04-23
  • 1970-01-01
  • 2012-12-15
  • 2012-02-23
相关资源
最近更新 更多