首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >保存设置时没有保存OrderedDictionary

保存设置时没有保存OrderedDictionary
EN

Stack Overflow用户
提问于 2015-12-09 10:12:39
回答 2查看 196关注 0票数 3

在我的应用程序中,我实现了几个Controls,以不同的方式浏览数据。在每个控件中,我都会显示一个TreeView,以允许用户从一个文件夹转到另一个文件夹。

我希望我的控件以一种通用的方式“记住”最后一棵选定的树(我的意思是,如果将来我添加了另一个控件,我不想做太多的调整)。因此,我在设置中添加了一个OrderedDictionary。我使用控件的类型名称作为键,节点的路径作为值。

由于无法为该词典设置默认值,所以我使用了以下技巧:

Settings.cs:

代码语言:javascript
复制
public OrderedDictionary Paths
{
    get
    {
        return LastsPaths ?? (LastsPaths = new OrderedDictionary());
    }
    set
    {
        this["LastsPaths"] = value;
    }
}

Settings.Designer.cs:

代码语言:javascript
复制
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
public global::System.Collections.Specialized.OrderedDictionary LastsPaths {
    get {
        return ((global::System.Collections.Specialized.OrderedDictionary)(this["LastsPaths"]));
    }
    set {
        this["LastsPaths"] = value;
    }
}

每次添加/更新值时,Save文件时间戳都会更改,但内容保持不变:

代码语言:javascript
复制
<setting name="LastsPaths" serializeAs="Xml">
    <value />
</setting>

它不适用于:

  • 调试模式下的App;
  • App在释放模式下;
  • 安装了应用程序。

我怎么才能解决这个问题?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-12-09 10:19:39

似乎是OrderedDictionary (和一般的通用字典) 不能序列化XML。

您可以将它包装在另一个手动序列化的类中。这样,您就不会直接将字典公开给XML序列化程序。为了实现这一点,您必须实现IXmlSerializable

票数 3
EN

Stack Overflow用户

发布于 2015-12-09 11:45:56

这可能就足以让你开始了。这继承了在保存调用期间需要的IXMLSerializable

代码语言:javascript
复制
[XmlRoot("PreviouslyVisitedPaths")]
public class PreviouslySelectedPaths : OrderedDictionary, IXmlSerializable
{

    #region Implementation of IXmlSerializable

    /// <summary>
    /// This method is reserved and should not be used. When implementing the IXmlSerializable interface, you should return null (Nothing in Visual Basic) from this method, and instead, if specifying a custom schema is required, apply the <see cref="T:System.Xml.Serialization.XmlSchemaProviderAttribute"/> to the class.
    /// </summary>
    /// <returns>
    /// An <see cref="T:System.Xml.Schema.XmlSchema"/> that describes the XML representation of the object that is produced by the <see cref="M:System.Xml.Serialization.IXmlSerializable.WriteXml(System.Xml.XmlWriter)"/> method and consumed by the <see cref="M:System.Xml.Serialization.IXmlSerializable.ReadXml(System.Xml.XmlReader)"/> method.
    /// </returns>
    public XmlSchema GetSchema()
    {
        return null;
    }

    /// <summary>
    /// Generates an object from its XML representation.
    /// </summary>
    /// <param name="reader">The <see cref="T:System.Xml.XmlReader"/> stream from which the object is deserialized. </param>
    public void ReadXml(XmlReader reader)
    {
        var keySerializer = new XmlSerializer(typeof(object));
        var valueSerializer = new XmlSerializer(typeof(object));

        var wasEmpty = reader.IsEmptyElement;
        reader.Read();

        if(wasEmpty)
        {
            return;
        }

        while(reader.NodeType != XmlNodeType.EndElement)
        {
            reader.ReadStartElement("item");

            reader.ReadStartElement("key");
            var key = keySerializer.Deserialize(reader);
            reader.ReadEndElement();

            reader.ReadStartElement("value");
            var value = valueSerializer.Deserialize(reader);
            reader.ReadEndElement();

            Add(key, value);

            reader.ReadEndElement();
            reader.MoveToContent();
        }
        reader.ReadEndElement();
    }

    /// <summary>
    /// Converts an object into its XML representation.
    /// </summary>
    /// <param name="writer">The <see cref="T:System.Xml.XmlWriter"/> stream to which the object is serialized. </param>
    public void WriteXml(XmlWriter writer)
    {
        var keySerializer = new XmlSerializer(typeof(object));
        var valueSerializer = new XmlSerializer(typeof(object));

        foreach(var key in Keys)
        {
            writer.WriteStartElement("item");

            writer.WriteStartElement("key");
            keySerializer.Serialize(writer, key);
            writer.WriteEndElement();

            writer.WriteStartElement("value");
            var value = this[key];
            valueSerializer.Serialize(writer, value);
            writer.WriteEndElement();

            writer.WriteEndElement();
        }

        #endregion
    }
}

然后将代码更改为:

代码语言:javascript
复制
public PreviouslySelectedPaths Paths
{
    get
    {
        return LastsPaths ?? (LastsPaths = new PreviouslySelectedPaths());
    }
    set
    {
        this["LastsPaths"] = value;
    }
}

您还需要使LastsPaths类型为PreviouslySelectedPaths

这仅仅是为了开始您的工作,您可能需要为IXMLSerializable方法设置一个星期,并为GetSchema()填写逻辑。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34176117

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档