Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/299.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# ApplicationSettingsBase为自定义集合写入空标记_C#_.net_Wpf_Serialization_Application Settings - Fatal编程技术网

C# ApplicationSettingsBase为自定义集合写入空标记

C# ApplicationSettingsBase为自定义集合写入空标记,c#,.net,wpf,serialization,application-settings,C#,.net,Wpf,Serialization,Application Settings,我已经断断续续地为此奋斗了好几天了。我需要存储一组自定义对象作为用户设置的一部分。基于谷歌的大量工作,从ApplicationSettingsBase构建一个preferences类似乎是一种合适的方法。我遇到的问题是,只要我尝试存储自定义类型的集合,就不会为该属性保存任何数据。如果我坚持使用基本类型的集合,例如字符串,那么事情就会正常工作。我有一个单独的概念验证项目,在过去的一天里,我一直在与之合作,以隔离到这个问题 此项目由一个WPF窗口组成,该窗口带有一个列表框和两个按钮“+”和“-“。我

我已经断断续续地为此奋斗了好几天了。我需要存储一组自定义对象作为用户设置的一部分。基于谷歌的大量工作,从
ApplicationSettingsBase
构建一个preferences类似乎是一种合适的方法。我遇到的问题是,只要我尝试存储自定义类型的集合,就不会为该属性保存任何数据。如果我坚持使用基本类型的集合,例如字符串,那么事情就会正常工作。我有一个单独的概念验证项目,在过去的一天里,我一直在与之合作,以隔离到这个问题

此项目由一个WPF窗口组成,该窗口带有一个列表框和两个按钮“+”和“-“。我有一个Prefs类,它有三个属性定义不同类型的集合。在我的窗口代码中,我将listbox绑定到其中一个列表,并且按钮可以向列表添加或从列表中删除项目。关闭窗口应将列表的内容保存到当前用户的users.config文件中。重新打开它应显示已保存列表的内容

如果我使用List1(
ObservableCollection
)并单击+按钮几次,然后关闭窗口,数据将正确保存到user.config。但是如果我更改并使用List2(
ObservableCollection
)或List3(
FooCollection
)我只是以一个空的值标记结束。我尝试实现
ISerializable
IXmlSerializable
,试图在不改变行为的情况下使其正常工作。事实上,在调试模式下运行并带有断点时,显示调用save方法时集合包含数据,但序列化接口方法你从来没有被叫过

我错过了什么

更新:我已经改变了我的方法,暂时将数据与user.config一起写入另一个文件,以便我可以在应用程序的其他部分取得一些进展。但我仍然想知道为什么application settings base无法记录我的收集数据

这是所有相关的代码,如果有人认为一个推荐的部分很重要,我会把它重新添加到帖子中

在向每个列表属性添加两个元素后返回user.config

<setting name="List1" serializeAs="Xml">
    <value>
        <ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema">
            <string>0</string>
            <string>1</string>
            <string>2</string>
        </ArrayOfString>
    </value>
</setting>
<setting name="List2" serializeAs="Xml">
    <value />
</setting>
<setting name="List3" serializeAs="Xml">
    <value />
</setting>
高级班

class Prefs : ApplicationSettingsBase
{
    [UserScopedSettingAttribute()]
    [DefaultSettingValueAttribute(null)]
    public System.Collections.ObjectModel.ObservableCollection<string> List1
    {
        get
        {
            System.Collections.ObjectModel.ObservableCollection<string> Value = this["List1"] as System.Collections.ObjectModel.ObservableCollection<string>;
            if (Value == null)
            {
                Value = new System.Collections.ObjectModel.ObservableCollection<string>();
                this["List1"] = Value;
            }
            return Value;
        }
    }

    [UserScopedSettingAttribute()]
    [DefaultSettingValueAttribute(null)]
    public System.Collections.ObjectModel.ObservableCollection<Foo> List2
    {
        get
        {
            System.Collections.ObjectModel.ObservableCollection<Foo> Value = this["List2"] as System.Collections.ObjectModel.ObservableCollection<Foo>;
            if (Value == null)
            {
                Value = new System.Collections.ObjectModel.ObservableCollection<Foo>();
                this["List2"] = Value;
            }
            return Value;
        }
    }

    [UserScopedSettingAttribute()]
    [DefaultSettingValueAttribute(null)]
    public FooCollection List3
    {
        get
        {
            FooCollection Value = this["List3"] as FooCollection;
            if (Value == null)
            {
                Value = new FooCollection();
                this["List3"] = Value;
            }
            return Value;
        }
    }
}
和FoodCollection类

[Serializable()]
class FooCollection : ICollection<Foo>, System.ComponentModel.INotifyPropertyChanged, INotifyCollectionChanged, ISerializable, IXmlSerializable
{
    List<Foo> Items;
    private const string PropName_Items = "Items";

    public FooCollection()
    {
        Items = new List<Foo>();
    }

    public Foo this[int index]
    {
/***Omitted for space***/
    }

    #region ICollection<Foo> Members
/***Omitted for space***/
    #endregion

    public void RemoveAt(int index)
    {
/***Omitted for space***/
    }

    #region IEnumerable Members
/***Omitted for space***/
    #endregion

    #region INotifyCollectionChanged Members
/***Omitted for space***/
    #endregion

    #region INotifyPropertyChanged Members
/***Omitted for space***/
    #endregion

    #region ISerializable Members
    public FooCollection(SerializationInfo info, StreamingContext context)
    {
        this.Items = (List<Foo>)info.GetValue(FooCollection.PropName_Items, typeof(List<Foo>));
    }
    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        info.AddValue(FooCollection.PropName_Items, this.Items);
    }
    #endregion

    #region IXmlSerializable Members
    public System.Xml.Schema.XmlSchema GetSchema()
    {
        return null;
    }

    public void ReadXml(System.Xml.XmlReader reader)
    {
        XmlSerializer FooSerializer = new XmlSerializer(typeof(Foo));

        reader.MoveToContent();
        bool Empty = reader.IsEmptyElement;
        reader.ReadStartElement();
        if (!Empty)
        {
            if (reader.IsStartElement(FooCollection.PropName_Items))
            {
                reader.ReadStartElement();

                while (reader.IsStartElement("Foo"))
                {
                    this.Items.Add((Foo)FooSerializer.Deserialize(reader));
                }

                reader.ReadEndElement();
            }

            reader.ReadEndElement();
        }
    }

    public void WriteXml(System.Xml.XmlWriter writer)
    {
        XmlSerializer FooSerializer = new XmlSerializer(typeof(Foo));

        writer.WriteStartElement(FooCollection.PropName_Items);

        foreach (Foo Item in Items)
        {
            writer.WriteStartElement("Foo");
            FooSerializer.Serialize(writer, Item);
            writer.WriteEndElement();//"Foo"
        }

        writer.WriteEndElement(); //FooCollection.PropName_Items
    }
    #endregion
}
[Serializable()]
FooCollection类:ICollection、System.ComponentModel.INotifyPropertyChanged、INotifyCollectionChanged、ISerializable、IXmlSerializable
{
清单项目;
private const string PropName_Items=“Items”;
公共图书馆馆藏()
{
项目=新列表();
}
public Foo this[int index]
{
/***为空间省略***/
}
#区域i集合成员
/***为空间省略***/
#端区
公共无效删除(整数索引)
{
/***为空间省略***/
}
#区域可数成员
/***为空间省略***/
#端区
#区域INotifyCollectionChanged成员
/***为空间省略***/
#端区
#区域INotifyProperty更改成员
/***为空间省略***/
#端区
#区域ISerializable成员
公共FooCollection(SerializationInfo信息、StreamingContext上下文)
{
this.Items=(List)info.GetValue(FooCollection.PropName_Items,typeof(List));
}
public void GetObjectData(SerializationInfo信息、StreamingContext上下文)
{
info.AddValue(FooCollection.PropName\u Items,this.Items);
}
#端区
#区域IXmlSerializable成员
public System.Xml.Schema.XmlSchema GetSchema()
{
返回null;
}
public void ReadXml(System.Xml.XmlReader)
{
XmlSerializer FooSerializer=新的XmlSerializer(typeof(Foo));
reader.MoveToContent();
bool Empty=reader.isemptyelment;
reader.ReadStartElement();
如果(!空)
{
if(reader.IsStartElement(FooCollection.PropName_Items))
{
reader.ReadStartElement();
while(reader.IsStartElement(“Foo”))
{
this.Items.Add((Foo)FooSerializer.Deserialize(reader));
}
reader.ReadEndElement();
}
reader.ReadEndElement();
}
}
public void WriteXml(System.Xml.XmlWriter)
{
XmlSerializer FooSerializer=新的XmlSerializer(typeof(Foo));
writer.writeStarteElement(FooCollection.PropName\u项);
foreach(项目中的Foo项目)
{
writer.writeStarteElement(“Foo”);
序列化(writer,Item);
writer.WriteEndElement();/“Foo”
}
writer.WriteEndElement();//FooCollection.PropName_项
}
#端区
}

我也为一个非常类似的问题挣扎了两天,但现在我发现了一个缺失的链接,这可能会有所帮助。 如果你和我的情况实际上相似,那么 类“Foo”和“FooCollection”需要显式公开

我假设,在List2(
ObservableCollection
)和
List3(FooCollection)
的情况下,.NET运行到
IXmlSerializable
,这在某种程度上需要显式的公共访问(跨越自己程序集的边界)

相反的选项List1(
ObservableCollection
)似乎是在一个平面字符串类型转换上运行的,它对(内部)类“Foo”很满意

(来自ApplicationsettingsBase文档:
ApplicationSettingsBase
使用两种主要机制来 序列化设置: 1) 如果存在可以与字符串进行转换的
TypeConverter
,我们就使用它。 2) 如果没有,我们就回到
XmlSerializer

亲切问候,,
Rudy

我也有一个类似的问题,我设法解决了,但我没有使用
可观察集合
,而是使用一个普通的
列表
作为我的一个类,包含为公共成员:string、int和bool,w
class Prefs : ApplicationSettingsBase
{
    [UserScopedSettingAttribute()]
    [DefaultSettingValueAttribute(null)]
    public System.Collections.ObjectModel.ObservableCollection<string> List1
    {
        get
        {
            System.Collections.ObjectModel.ObservableCollection<string> Value = this["List1"] as System.Collections.ObjectModel.ObservableCollection<string>;
            if (Value == null)
            {
                Value = new System.Collections.ObjectModel.ObservableCollection<string>();
                this["List1"] = Value;
            }
            return Value;
        }
    }

    [UserScopedSettingAttribute()]
    [DefaultSettingValueAttribute(null)]
    public System.Collections.ObjectModel.ObservableCollection<Foo> List2
    {
        get
        {
            System.Collections.ObjectModel.ObservableCollection<Foo> Value = this["List2"] as System.Collections.ObjectModel.ObservableCollection<Foo>;
            if (Value == null)
            {
                Value = new System.Collections.ObjectModel.ObservableCollection<Foo>();
                this["List2"] = Value;
            }
            return Value;
        }
    }

    [UserScopedSettingAttribute()]
    [DefaultSettingValueAttribute(null)]
    public FooCollection List3
    {
        get
        {
            FooCollection Value = this["List3"] as FooCollection;
            if (Value == null)
            {
                Value = new FooCollection();
                this["List3"] = Value;
            }
            return Value;
        }
    }
}
[Serializable()]
class Foo : System.ComponentModel.INotifyPropertyChanged, ISerializable, IXmlSerializable
{
    private string _Name;
    private const string PropName_Name = "Name";
    public string Name
    {
        get { return this._Name; }
        set
        {
            if (value != this._Name)
            {
                this._Name = value;
                RaisePropertyChanged(Foo.PropName_Name);
            }
        }
    }
    public override string ToString()
    {
        return Name;
    }

    public Foo() { }
    public Foo(string name)
    {
        this._Name = name;
    }

    #region INotifyPropertyChanged Members
/***Omitted for space***/
    #endregion

    #region ISerializable Members
    public Foo(SerializationInfo info, StreamingContext context)
    {
        this._Name = (string)info.GetValue(Foo.PropName_Name, typeof(string));
    }
    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        info.AddValue(Foo.PropName_Name, this._Name);
    }
    #endregion

    #region IXmlSerializable Members
    public System.Xml.Schema.XmlSchema GetSchema()
    {
        return null;
    }

    public void ReadXml(System.Xml.XmlReader reader)
    {
        reader.MoveToContent();
        _Name = reader.GetAttribute(Foo.PropName_Name);
        bool Empty = reader.IsEmptyElement;
        reader.ReadStartElement();
        if (!Empty)
        {
            reader.ReadEndElement();
        }
    }

    public void WriteXml(System.Xml.XmlWriter writer)
    {
        writer.WriteAttributeString(Foo.PropName_Name, _Name);
    }
    #endregion
}
[Serializable()]
class FooCollection : ICollection<Foo>, System.ComponentModel.INotifyPropertyChanged, INotifyCollectionChanged, ISerializable, IXmlSerializable
{
    List<Foo> Items;
    private const string PropName_Items = "Items";

    public FooCollection()
    {
        Items = new List<Foo>();
    }

    public Foo this[int index]
    {
/***Omitted for space***/
    }

    #region ICollection<Foo> Members
/***Omitted for space***/
    #endregion

    public void RemoveAt(int index)
    {
/***Omitted for space***/
    }

    #region IEnumerable Members
/***Omitted for space***/
    #endregion

    #region INotifyCollectionChanged Members
/***Omitted for space***/
    #endregion

    #region INotifyPropertyChanged Members
/***Omitted for space***/
    #endregion

    #region ISerializable Members
    public FooCollection(SerializationInfo info, StreamingContext context)
    {
        this.Items = (List<Foo>)info.GetValue(FooCollection.PropName_Items, typeof(List<Foo>));
    }
    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        info.AddValue(FooCollection.PropName_Items, this.Items);
    }
    #endregion

    #region IXmlSerializable Members
    public System.Xml.Schema.XmlSchema GetSchema()
    {
        return null;
    }

    public void ReadXml(System.Xml.XmlReader reader)
    {
        XmlSerializer FooSerializer = new XmlSerializer(typeof(Foo));

        reader.MoveToContent();
        bool Empty = reader.IsEmptyElement;
        reader.ReadStartElement();
        if (!Empty)
        {
            if (reader.IsStartElement(FooCollection.PropName_Items))
            {
                reader.ReadStartElement();

                while (reader.IsStartElement("Foo"))
                {
                    this.Items.Add((Foo)FooSerializer.Deserialize(reader));
                }

                reader.ReadEndElement();
            }

            reader.ReadEndElement();
        }
    }

    public void WriteXml(System.Xml.XmlWriter writer)
    {
        XmlSerializer FooSerializer = new XmlSerializer(typeof(Foo));

        writer.WriteStartElement(FooCollection.PropName_Items);

        foreach (Foo Item in Items)
        {
            writer.WriteStartElement("Foo");
            FooSerializer.Serialize(writer, Item);
            writer.WriteEndElement();//"Foo"
        }

        writer.WriteEndElement(); //FooCollection.PropName_Items
    }
    #endregion
}