PropertyGrid-多选时的属性 [英] PropertyGrid - Attributes while multiselecting

查看:131
本文介绍了PropertyGrid-多选时的属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

您好,专家,

在应用程序中,我有一个System.Windows.Forms.PropertyGrid可以让用户更改某些业务模型属性.
这些属性之一是枚举类型,经常被类似地使用,但是对于某些属性,某些值将不显示.因此,我创建了SelectiveEnumAttribute.在自定义TypeConverterGetStandardValues()方法中使用它,以仅向用户显示相关的枚举值.

这种基于属性的枚举值的选择性隐藏通常可以正常工作,但是在同时编辑多个对象时则无效.

无论哪种情况,都使用PropertyGrid.SelectedObjects = objectArray.

[Edit2]
似乎我的第一个例子太狭窄了.我感兴趣的属性控制自定义TypeConverter的某些行为.因此,我需要从TypeConverter的方法中访问给定属性的属性.

 blic  class  MyAttribute:属性
{
}


公共  MyTypeConverter:EnumConverter
{
    公共 MyTypeConverter(类型)
        :基本(类型)
    {}


    公共 覆盖  bool  GetStandardValuesSupported(ITypeDescriptorContext context)
    {
         int  attributeCount = context.PropertyDescriptor.Attributes.Count; // 在此处设置断点.

        返回 基本.GetStandardValuesSupported(context);
    }
}


公共  MyBusinessObject
{
    公共 枚举 AllValues
    {
        FirstValue,
        SecondValue,
        ThirdValue,
        FourthValue,
        第五价值
    }

    私有 AllValues _oneValue = AllValues.FirstValue;

    [MyAttribute]
    [TypeConverter( typeof (MyTypeConverter))]
    公共 AllValues值
    {
        获取 {返回(_oneValue); }
         set  {_oneValue =  value ; }
    }
}


公共 部分  class  Form1:表单
{
    公共 Form1()
    {
        InitializeComponent();
    }


    受保护的 覆盖  void  OnShown(EventArgs e)
    {
        基本 .OnShown(e);

        MyBusinessObject business1 =  MyBusinessObject();
        MyBusinessObject business2 =  MyBusinessObject();

        //  propertyGrid1.SelectedObjects =新对象[] {business1}; 
        propertyGrid1.SelectedObjects =  对象 [] {business1,business2};
    }
} 



将多个对象馈入PropertyGrid时,附加到其属性的属性似乎完全消失了.即使对象具有相同的类型,因此它们的属性"属性也是相同的(在值上,甚至在存在上).

MyTypeConverter.GetStandardValuesSupported()中进行检查.在网格中显示多个对象时,属性计数等于零.

只要只显示一个对象,此属性集合就包含有问题的属性,并且我可以访问它们的存储值(为简单起见,在示例中未显示).
[/Edit2]

解决方案

在提到的情况下,要在PropertyGrid中显示多个对象,参数类型为MyTypeConverter.GetStandardValuesSupported(context)更改为System.Windows.Forms.PropertyGridInternal.MergePropertyDescriptor.

此类型有一个专用字段private PropertyDescriptor[] descriptors,由于其访问级别而不能直接使用.

但是,使用反射,我们可以访问

 System.Type propertyType = context.PropertyDescriptor.GetType();.
System.Reflection.FieldInfo fieldInfo = propertyType.GetField(
    " ,
    System.Reflection.BindingFlags.NonPublic
    | System.Reflection.BindingFlags.Instance
);
PropertyDescriptors []描述符=
    (PropertyDescriptor [])(fieldInfo.GetValue(context.PropertyDescriptor)); 

现在我们可以分析每个单独的PropertyDescriptor.就我而言,我做了一些测试.

private void button1_Click(object sender, EventArgs e)
        {
            propertyGrid1.SelectedObjects = new object[]{_businessObject1};
            Type t = _businessObject1.GetType();
            PropertyInfo pi = t.GetProperty("SomeValue");
            MessageBox.Show(pi.GetCustomAttributes(false)[0].ToString());
        }

        private void button2_Click(object sender, EventArgs e)
        {
            propertyGrid1.SelectedObjects = new object[] { _businessObject1, _businessObject2 };
            Type t1 = _businessObject1.GetType();
            PropertyInfo pi1 = t1.GetProperty("SomeValue");

            Type t2 = _businessObject2.GetType();
            PropertyInfo pi2 = t2.GetProperty("SomeValue");

            MessageBox.Show(pi1.GetCustomAttributes(false)[0].ToString() + "\r\n" + pi2.GetCustomAttributes(false)[0].ToString());
            
        }


在这两种情况下,我都可以看到该属性仍然存在.
也许我完全误解了您的问题.


Hi experts,

in an application I have a System.Windows.Forms.PropertyGrid to let user change some business model properties.
One of these properties is of an enumerated type that is often used similarly, but for a few properties, some values shall not be displayed. Therefore I created SelectiveEnumAttribute. It is used in a custom TypeConverter''s GetStandardValues() method to display only the relevant enum values to the user.

This attribute-based selective hiding of enumeration values works in general, but it doesn''t when editing multiple objects at the same time.

In either case, PropertyGrid.SelectedObjects = objectArray is used.

[Edit2]
Seems my first example has been too narrow. The attributes of interest for me control some of the behaviour of a custom TypeConverter. Therefore I need access to a given property''s attributes from within the TypeConverter''s methods.

blic class MyAttribute : Attribute
{
}


public class MyTypeConverter : EnumConverter
{
    public MyTypeConverter(Type type)
        : base(type)
    { }


    public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
    {
        int attributeCount = context.PropertyDescriptor.Attributes.Count;   // Set Breakpoint here.

        return base.GetStandardValuesSupported(context);
    }
}


public class MyBusinessObject
{
    public enum AllValues
    {
        FirstValue,
        SecondValue,
        ThirdValue,
        FourthValue,
        FifthValue
    }

    private AllValues _oneValue = AllValues.FirstValue;

    [MyAttribute]
    [TypeConverter(typeof(MyTypeConverter))]
    public AllValues Value
    {
        get { return (_oneValue); }
        set { _oneValue = value; }
    }
}


public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }


    protected override void OnShown(EventArgs e)
    {
        base.OnShown(e);

        MyBusinessObject business1 = new MyBusinessObject();
        MyBusinessObject business2 = new MyBusinessObject();

        //propertyGrid1.SelectedObjects = new object[] { business1 };
        propertyGrid1.SelectedObjects = new object[] { business1, business2 };
    }
}



When feeding multiple objects into PropertyGrid, the attributes attached to their properties seem to simply vanish. Even though objects are of the same type and therefore, their properties'' attributes are identical (in value and even in existence).

Check this in MyTypeConverter.GetStandardValuesSupported(). When showing multiple objects in the grid, the attribute count equals zero.

As long as there is only one object to show, this attribute collection contains the attributes in question and I can access their stored values (not shown in example for simplicity).
[/Edit2]

How can I preserve the attached attribute while multiselecting objects for the PropertyGrid?

解决方案

In the mentioned case with multiple objects to be shown in PropertyGrid the parameter type of MyTypeConverter.GetStandardValuesSupported(context) changes to System.Windows.Forms.PropertyGridInternal.MergePropertyDescriptor.

This type has a private field private PropertyDescriptor[] descriptors, which can not be used directly due to it''s access level.

But using Reflection we can gain access

System.Type propertyType = context.PropertyDescriptor.GetType();
System.Reflection.FieldInfo fieldInfo = propertyType.GetField(
    "descriptors",
    System.Reflection.BindingFlags.NonPublic
    | System.Reflection.BindingFlags.Instance
);
PropertyDescriptors[] descriptors =
    (PropertyDescriptor[])(fieldInfo.GetValue(context.PropertyDescriptor));

Now we can analyze each separate PropertyDescriptor.


I don''t know much about attributes but nosy as I am, I did some test.

private void button1_Click(object sender, EventArgs e)
        {
            propertyGrid1.SelectedObjects = new object[]{_businessObject1};
            Type t = _businessObject1.GetType();
            PropertyInfo pi = t.GetProperty("SomeValue");
            MessageBox.Show(pi.GetCustomAttributes(false)[0].ToString());
        }

        private void button2_Click(object sender, EventArgs e)
        {
            propertyGrid1.SelectedObjects = new object[] { _businessObject1, _businessObject2 };
            Type t1 = _businessObject1.GetType();
            PropertyInfo pi1 = t1.GetProperty("SomeValue");

            Type t2 = _businessObject2.GetType();
            PropertyInfo pi2 = t2.GetProperty("SomeValue");

            MessageBox.Show(pi1.GetCustomAttributes(false)[0].ToString() + "\r\n" + pi2.GetCustomAttributes(false)[0].ToString());
            
        }


In both cases I can see that the attribute still exists.
Maybe I completely misunderstand your problem.


这篇关于PropertyGrid-多选时的属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆