1

Here is what I tried but I get this error:

Error CS0029 Cannot implicitly convert type 'ListBoxAndDictionary.CountriesAndCities' to 'System.Collections.Generic.Dictionary<string, System.Collections.Generic.List>'

Here is my code:

private Dictionary<string, List<string>> dictCountryAndCities = new
      Dictionary<string, List<string>>();

private void button12_Click(object sender, EventArgs e)
{
    SaveFileDialog sfd = new SaveFileDialog();
    sfd.FileName = "CountriesAndCities";
    sfd.DefaultExt = ".xml";
    sfd.Filter = "XML (*.xml)|*.xml|All Files (*.*)|*.*";
    var sfdResult = sfd.ShowDialog();
    if (sfdResult == DialogResult.Cancel) 
        return;
    var container = new CountriesAndCities
    {
        DictCountriesAndCities = dictCountryAndCities
    };
    using (var writer = XmlWriter.Create(sfd.FileName)) 
        (new XmlSerializer(typeof(CountriesAndCities))).Serialize(writer, container);
}

private void button11_Click(object sender, EventArgs e)
{
    OpenFileDialog ofd = new OpenFileDialog();
    ofd.DefaultExt = ".xml";
    ofd.Filter = "XML (*.xml)|*.xml|All Files (*.*)|*.*";
    var ofdResult = ofd.ShowDialog();
    if (ofdResult == DialogResult.Cancel) 
        return;
    dictCountryAndCities = new Dictionary<string, List<string>>();

    XmlSerializer serializer = new XmlSerializer(typeof(CountriesAndCities));
    using (var reader = new StreamReader(ofd.FileName))
    {
        dictCountryAndCities = serializer.Deserialize(reader) as CountriesAndCities;

        //Error CS0029 Cannot implicitly convert type 'ListBoxAndDictionary.CountriesAndCities' to 'System.Collections.Generic.Dictionary<string, System.Collections.Generic.List<string>>'
    }

    //binding DataSource for listBox1
    listBox1.DataSource = dictCountryAndCities.Keys.ToList();
}

[Serializable]
[XmlRoot("CountriesAndCities")]
public class CountriesAndCities
{
    public List<Country> Name
    {
        get { return DictCountriesAndCities.Select(x => new Country { CountryName = x.Key, Cities = x.Value }).ToList(); }
        set { DictCountriesAndCities = value.ToDictionary(x => x.CountryName, x => x.Cities); }
    }
    [XmlIgnore]
    public Dictionary<string, List<string>> DictCountriesAndCities { get; set; }
}

[Serializable]
public class Country
{
    public string CountryName { get; set; }
    public List<string> Cities { get; set; }
}
7
  • @alphabeta How we can help you if you don't show your xml? Commented Apr 29, 2023 at 16:32
  • There is no problems with deserialization at all. You have simply invalid cast from your custom CountriesAndCities class to the Dictionary<string, List<string>> in the line dictCountryAndCities = serializer.Deserialize(...). You need to provide cast operator or implement data conversion in any other way. Commented Apr 29, 2023 at 16:33
  • 1
    You need to handle dictionaries different than other objects. See : stackoverflow.com/questions/3671259/… Commented Apr 29, 2023 at 16:37
  • Thanks Serg, but how to do this? Can you give an example? Commented Apr 29, 2023 at 16:38
  • @alphabeta Thanks, but the image can not be used. You can past an xml as a text inside of your question. Just click a edit link Commented Apr 29, 2023 at 16:56

2 Answers 2

0

this code works for me

XDocument doc = XDocument.Load(FILENAME);

Dictionary<string, List<string>> dict = doc.Root.Elements("Country")
                   .ToDictionary(c => (string)c.Element("CountryName"),
                                 c => c.Descendants("Cities").Elements("string")
                   .Select(d => d.Value)
                   .ToList());

you can use this, but I don't see any sense to convert to a dictionary but use only keys.

listBox1.DataSource = dict.Keys.ToList();

this has a little more sense, but not very much too

List<string> source=new List<string>();                              
foreach (var item in dict)
{
        source.Add($"--- {item.Key} ---");
        source.AddRange(item.Value);
}                                
listBox1.DataSource = dict.Keys.ToList();

you need a TreeView user control for a dictionary

Sign up to request clarification or add additional context in comments.

6 Comments

Your code gives error when I try to populate listBox1 with Key.
@alphabeta Your question is how to deserialize xml to a dictionary. Why should I guess what are you need this data for? I think you cannot use dictionary as a source for a list box. You have to post more details what kind of list box you are trying to create, but you even too lazy to post your xml. How people can help you? There are dozens of different list boxes. YOu have to post the picture how are you to arrange a dictionary to a list? it is very weird. You have at least post ListBoxAndDictionary.CountriesAndCities class
I tried many times to post XML as text but I can't because of this message. "It looks like your post is mostly code; please add some more details."
@alphabeta You must be trying to create a new post. You have to edit the one you published already
No, I edit my first post but it is not accepted because of this message. I am new on this forum and I do not understand what to do. English is not my native language, I use Google Translate.
|
-1

You have a few problems with your XML serialization code.

Firstly, you need to modify your CountriesAndCities DTO as follows, replacing the List<Country> Name surrogate property with a Country [] Name property instead:

[XmlRoot("CountriesAndCities")]
public class CountriesAndCities
{
    public Country [] Name      // Replace the List<Country> with Country []
    {
        get { return DictCountriesAndCities.Select(x => new Country { CountryName = x.Key, Cities = x.Value }).ToArray(); }
        set { DictCountriesAndCities = value?.ToDictionary(x => x.CountryName, x => x.Cities); }
    }
    [XmlIgnore]
    public Dictionary<string, List<string>> DictCountriesAndCities { get; set; }
}

public class Country
{
    public string CountryName { get; set; }
    public List<string> Cities { get; set; }
}

Secondly, modify your serialization code as follows:

var container = new CountriesAndCities
{
    DictCountriesAndCities = dictCountriesAndCities,
};
using (var writer = XmlWriter.Create(sfd.FileName, new XmlWriterSettings { Indent = true })) // Indentation is for visualization purposes only
    (new XmlSerializer(typeof(CountriesAndCities))).Serialize(writer, container);

Finally, change your deserialization code as follows:

using (var reader = new StreamReader(ofd.FileName))
{
    dictCountriesAndCities = ((new XmlSerializer(typeof(CountriesAndCities))).Deserialize(reader) as CountriesAndCities)
        ?.DictCountriesAndCities;
}

Notes:

  • Your "Error CS0029" is caused because you attempt to assign a value of type CountriesAndCities to a Dictionary<string, List<string>>. Instead, you must access the property DictCountriesAndCities.

  • In your method button11_Click() you are deserializing your XML into a local variable dictCountryAndCities, then binding to its keys:

     dictCountryAndCities = new Dictionary<string, List<string>>();
    
     XmlSerializer serializer = new XmlSerializer(typeof(CountriesAndCities));
     using (var reader = new StreamReader(ofd.FileName))
     {
         dictCountryAndCities = serializer.Deserialize(reader) as CountriesAndCities;
    
         //Error CS0029 Cannot implicitly convert type 'ListBoxAndDictionary.CountriesAndCities' to 'System.Collections.Generic.Dictionary<string, System.Collections.Generic.List<string>>'
     }
    

    You are not updating the class member dictCountryAndCities at all. This seems wrong. However, it's not clear from your question what you want to be doing there, so I can't really recommend a fix.

  • The [Serializable] attribute is not required or used by XmlSerializer, and can be removed.

  • For an explanation as to why you should use Country [] instead of List<Country> for your surrogate Name property, see this answer to Cannot deserialize XML into a list using XML Deserializer.

Demo fiddle here.

1 Comment

Thank you all for your patience with me. And a BIG thank you for @dbc! Your code works perfectly.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.