C# 如何在属性网格中加载xml文档

C# 如何在属性网格中加载xml文档,c#,winforms,C#,Winforms,如何在属性网格中加载xml文档并将xml标记显示为属性网格中的属性 对于上面的问题,我在属性网格中得到了答案(由Marc Gravell代码),但由于可扩展对象转换器,我得到了所有需要删除的属性的“+”,如何删除它不是一个简单的请求;您必须编写一个包装类(对于XmlNode),该类具有自定义的TypeConverter(或者:ICustomTypeDescriptor或TypeDescriptionProvider,但TypeConverter是最简单的)。然后编写一个自定义的PropertyD

如何在属性网格中加载xml文档并将xml标记显示为属性网格中的属性


对于上面的问题,我在属性网格中得到了答案(由Marc Gravell代码),但由于可扩展对象转换器,我得到了所有需要删除的属性的“+”,如何删除它不是一个简单的请求;您必须编写一个包装类(对于
XmlNode
),该类具有自定义的
TypeConverter
(或者:
ICustomTypeDescriptor
TypeDescriptionProvider
,但
TypeConverter
是最简单的)。然后编写一个自定义的
PropertyDescriptor
(或多个)来表示伪属性。假设
TypeConverter
,重写
GetProperties
以返回人工属性(用于值或子节点)

树视图向上构建它会更容易


嗯,;这并不容易;这是一个非常未经测试的开始点-粗糙且几乎没有功能,但无论如何,它在这里

有关此处发生的情况的更多参考,请特别查看模拟属性的
PropertyDescriptor
,以及提供属性的
TypeConverter
(尽管还有其他选项)

其他一些可能有帮助的文章:

代码:

使用系统;
使用System.Collections.Generic;
使用系统组件模型;
使用System.Windows.Forms;
使用System.Xml;
命名空间DemoApp
{
班级计划
{
[状态线程]
静态void Main()
{
Application.EnableVisualStyles();
XmlDocument doc=新的XmlDocument();
doc.LoadXml(“dhij”);
使用(var grid=newpropertygrid{Dock=DockStyle.Fill,
SelectedObject=newXMLNodeWrapper(doc.DocumentElement)})
使用(var form=newform{Controls={grid}})
{
申请表格;
}
}
}
}
[TypeConverter(typeof(XmlNodeWrapperConverter))]
类XmlNodeWrapper
{
私有只读XmlNode;
公共XmlNodeWrapper(XmlNode节点){this.node=node;}
类XmlNodeWrapperConverter:ExpandableObjectConverter
{
公共重写属性描述或集合GetProperties(ITypeDescriptorContext上下文、对象值、属性[]属性)
{
列表道具=新列表();
XmlElement el=((XmlNodeWrapper)值).node作为XmlElement;
如果(el!=null)
{
foreach(el.Attributes中的XmlAttribute属性)
{
添加(新的XmlNodeWrapperPropertyDescriptor(attr));
}
}
foreach(xmlnodechild in((XmlNodeWrapper)值).node.ChildNodes)
{
添加(新的XmlNodeWrapperPropertyDescriptor(子));
}
返回新的PropertyDescriptorCollection(props.ToArray(),true);
}
公共重写对象转换为(ITypeDescriptorContext上下文,System.Globalization.CultureInfo区域性,对象值,类型destinationType)
{
返回destinationType==typeof(字符串)
((XmlNodeWrapper)值).node.InnerXml
:base.ConvertTo(上下文、区域性、值、目标类型);
}
}
类XmlNodeWrapperPropertyDescriptor:PropertyDescriptor
{
私有静态只读属性[]nix=新属性[0];
私有只读XmlNode;
公共XmlNodeWrapperPropertyDescriptor(XmlNode节点):base(GetName(node),nix)
{
this.node=节点;
}
静态字符串GetName(XmlNode节点)
{
开关(node.NodeType)
{
case XmlNodeType.Attribute:返回“@”+node.Name;
case-XmlNodeType.Element:返回node.Name;
case XmlNodeType.Comment:返回“”;
case-XmlNodeType.Text:return“(Text)”;
默认值:return node.NodeType+“:”+node.Name;
}
}
公共重写bool ShouldSerializeValue(对象组件)
{
返回false;
}
公共覆盖无效设置值(对象组件、对象值)
{
Value=(字符串)值;
}
公共覆盖布尔CanResetValue(对象组件)
{
return!IsReadOnly;
}
公共替代无效重置值(对象组件)
{
设置值(组件“”);
}
公共覆盖类型PropertyType
{
得到{
开关(node.NodeType)
{
case XmlNodeType.Element:
返回类型(XmlNodeWrapper);
违约:
返回类型(字符串);
}
}
}
公共覆盖布尔为只读
{
得到{
开关(node.NodeType)
{
case XmlNodeType.Attribute:
案例XmlNodeType.Text:
返回false;
违约:
返回true;
}
}
}
公共覆盖对象GetValue(对象组件)
{
开关(node.NodeType)
{
case XmlNodeType.Element:
返回新的XmlNodeWrapper(节点);
违约:
返回节点值;
}
}
公共重写类型ComponentType
{
获取{return typeof(XmlNodeWrapper);}
}
}
}

@subbiah请允许我强调—运行时伪属性是.NET中一个棘手的角落;只有当您对.NET非常有信心,并且在理想情况下已经使用了
System.ComponentModel
befo时,才可以看到这一点
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;
using System.Xml;

namespace DemoApp
{
    class Program
    {
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();

            XmlDocument doc = new XmlDocument();
            doc.LoadXml("<xml a=\"b\"><c>d<e f=\"g\">h</e>i</c>j</xml>");
            using (var grid = new PropertyGrid { Dock = DockStyle.Fill,
                SelectedObject = new XmlNodeWrapper(doc.DocumentElement)})
            using (var form = new Form { Controls = {grid}})
            {
                Application.Run(form);
            }
        }
    }
}
[TypeConverter(typeof(XmlNodeWrapperConverter))]
class XmlNodeWrapper
{
    private readonly XmlNode node;
    public XmlNodeWrapper(XmlNode node) { this.node = node; }
    class XmlNodeWrapperConverter : ExpandableObjectConverter
    {
        public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)
        {
            List<PropertyDescriptor> props = new List<PropertyDescriptor>();
            XmlElement el = ((XmlNodeWrapper)value).node as XmlElement;
            if (el != null)
            {
                foreach (XmlAttribute attr in el.Attributes)
                {
                    props.Add(new XmlNodeWrapperPropertyDescriptor(attr));
                }
            }
            foreach (XmlNode child in ((XmlNodeWrapper)value).node.ChildNodes)
            {
                props.Add(new XmlNodeWrapperPropertyDescriptor(child));
            }
            return new PropertyDescriptorCollection(props.ToArray(), true);
        }
        public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
        {
            return destinationType == typeof(string)
                ? ((XmlNodeWrapper)value).node.InnerXml
                : base.ConvertTo(context, culture, value, destinationType);
        }
    }
    class XmlNodeWrapperPropertyDescriptor : PropertyDescriptor
    {
        private static readonly Attribute[] nix = new Attribute[0];
        private readonly XmlNode node;
        public XmlNodeWrapperPropertyDescriptor(XmlNode node) : base(GetName(node), nix)
        {
            this.node = node;
        }
        static string GetName(XmlNode node)
        {
            switch (node.NodeType)
            {
                case XmlNodeType.Attribute: return "@" + node.Name;
                case XmlNodeType.Element: return node.Name;
                case XmlNodeType.Comment: return "<!-- -->";
                case XmlNodeType.Text: return "(text)";
                default: return node.NodeType + ":" + node.Name;
            }
        }
        public override bool ShouldSerializeValue(object component)
        {
            return false;
        }
        public override void SetValue(object component, object value)
        {
            node.Value = (string)value;
        }
        public override bool CanResetValue(object component)
        {
            return !IsReadOnly;
        }
        public override void ResetValue(object component)
        {
            SetValue(component, "");
        }
        public override Type PropertyType
        {
            get {
                switch (node.NodeType)
                {
                    case XmlNodeType.Element:
                        return typeof(XmlNodeWrapper);
                    default:
                        return typeof(string);
                }
            }
        }
        public override bool IsReadOnly
        {
            get {
                switch (node.NodeType)
                {
                    case XmlNodeType.Attribute:
                    case XmlNodeType.Text:
                        return false;
                    default:
                        return true;
                }
            }
        }
        public override object GetValue(object component)
        {
            switch (node.NodeType)
            {
                case XmlNodeType.Element:
                    return new XmlNodeWrapper(node);
                default:
                    return node.Value;
            }
        }
        public override Type ComponentType
        {
            get { return typeof(XmlNodeWrapper); }
        }
    }
}