【问题标题】:How to load xml document in property grid如何在属性网格中加载 xml 文档
【发布时间】:2011-06-03 05:31:34
【问题描述】:

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

对于上述问题,我在属性网格中得到了答案(由 Marc Gravell 代码),但由于可扩展对象转换器,我得到所有属性的“+”,我需要删除它,如何删除

【问题讨论】:

    标签: c# winforms


    【解决方案1】:

    这不是一个简单的要求;您必须编写一个具有自定义TypeConverter 的包装类(对于XmlNode)(或者:ICustomTypeDescriptorTypeDescriptionProvider,但TypeConverter 是最简单的)。然后编写一个自定义的PropertyDescriptor(或多个)来表示假属性。假设TypeConverter,覆盖GetProperties 以返回人工属性(用于值或子节点)。

    TreeView向上构建会更容易...


    好的;这不容易;这是一个非常未经测试的开始点 - 粗糙且几乎没有功能,但无论如何都是这样。

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

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

    代码:

    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); }
            }
        }
    }
    

    【讨论】:

    • @subbiah 让我强调一下——运行时伪属性是 .NET 的一个棘手的角落;仅当您对 .NET 真正有信心时才查看此内容,并且理想情况下之前 comsumed System.ComponentModel (作为创作,它往往需要了解正在发生的事情)]
    • 如果您知道任何与此相关的材料,请给我建议
    猜你喜欢
    • 2020-03-09
    • 1970-01-01
    • 2019-01-29
    • 1970-01-01
    • 2023-04-05
    • 2011-06-20
    • 1970-01-01
    • 2021-10-24
    • 1970-01-01
    相关资源
    最近更新 更多