Как читать значения из XML-документа для создания ComboBox?
Я пытаюсь прочитать xml файл, который я хочу сделать для моей мамы. Так что в основном это то, что я хочу сделать:
- A
ComboBox
который покажет все имена овощей в XML. - после выбора овоща, второй
ComboBox
покажет имена рецептов в XML, которые могут использовать овощ, выбранный в первомComboBox
для приготовления пищи. - последний, с ОК
Button
выбранный рецепт будет читать Путь к файлу, который ведет к рецепту.
XML я написал
<Vegetables>
<vegetable name="Carrot">
<recipe name="ABCrecipe">
<FilePath>C:</FilePath>
</recipe>
<recipe name="DEFrecipe">
<FilePath>D:</FilePath>
</recipe>
</vegetable>
<vegetable name="Potato">
<recipe name="CBArecipe">
<FilePath>E:</FilePath>
</recipe>
<recipe name"FEDrecipe">
<FilePath>F:</FilePath>
</recipe>
</vegetable>
</Vegetables>
C# код
private void Form1_Load(object sender, EventArgs e)
{
XmlDocument xDoc = new XmlDocument();
xDoc.Load("Recipe_List.xml");
XmlNodeList vegetables = xDoc.GetElementsByTagName("Vegetable");
for (int i = 0; i < vegetables.Count; i++)
{
comboBox1.Items.Add(vegetables[i].Attributes["name"].InnerText);
}
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
//I'm lost at this place.
}
первый ComboBox
теперь может отображать имена овощей, но как я могу сделать 2nd ComboBox
читать рецепты?
3 ответов
ваш xml должен быть реструктурирован, так как вы смешиваете данные при вводе имен рецептов и узла пути к файлу в качестве значения узла рецепта
вот лучший подход:
<Vegetables>
<vegetable name="Carrot">
<recipe name="ABCrecipe">
<FilePath>C:\</FilePath>
</recipe>
<recipe name="DEFrecipe">
<FilePath>D:\</FilePath>
</recipe>
</vegetable>
<vegetable name="Potato">
<recipe name="CBArecipe">
<FilePath>E:\</FilePath>
</recipe>
<recipe name="FEDrecipe">
<FilePath>F:\</FilePath>
</recipe>
</vegetable>
</Vegetables>
Итак, чтобы отобразить рецепты, вам нужно извлечь атрибут узла recipe. Как это сделать описано здесь: как прочитать значение атрибута из XmlNode в C#?
Edit: исправлена структура xml из-за комментариев. Спасибо
если вы хотите иметь возможность получить имя овоща из документа, самое простое, что нужно сделать, это определить его как свой собственный отдельный кусок данных. Нет ничего недействительным о том, что вы сделали, но это сделало его довольно трудно добраться до данных, которые вы хотите.
если вы можете, измените структуру на что-то вроде этого, чтобы облегчить вашу жизнь:
<vegetables>
<vegetable>
<name>Carrot</name>
<recipe>
<name>ABCrecipe</name>
<path>C:\</path>
</recipe>
<recipe>
<name>DEFrecipe</name>
<path>D:\</path>
</recipe>
</vegetable>
</vegetables>
предполагая, что вы используете .NET 3.5 или новее, у вас будет доступ к the LINQ-to-XML API-интерфейсы. Они предоставляют упрощенный способ чтения значений из XML-документа и должны сделать решение этой проблемы немного проще.
вы создаете документ, используя:
var document = XDocument.Load("Recipe_List.xml");
тогда вы можете написать запрос, чтобы получить растительные элементы, как это:
var vegetables = document
.Element(XName.Get("vegetables"))
.Elements(XName.Get("vegetable"));
если у вас есть эти элементы, вы можете получить их имена, как это:
var vegNames = vegetables.Select(ele => ele.Element(XName.Get("name")).Value);
затем вы можете включить эту информацию в вашем поле действительно легко:
foreach (string name in vegNames)
{
comboBox1.Items.Add(name);
}
Я предполагаю, что вы используете C# в .Net 4.0 framework
вы можете отформатировать xml следующим образом:
<Vegetables>
<vegetable>
<name>Carrot</name>
<recipe>
<name>ABCrecipe</name>
<FilePath>C:\</FilePath>
</recipe>
<recipe>
<name>DEFrecipe</name>
<FilePath>D:\</FilePath>
</recipe>
</vegetable>
<vegetable>
<name>Potato</name>
<recipe>
<name>CBArecipe</name>
<FilePath>E:\</FilePath>
</recipe>
<recipe>
<name>FEDrecipe</name>
<FilePath>F:\</FilePath>
</recipe>
</vegetable>
</Vegetables>
тогда просто используйте этот запрос, чтобы выбрать эти элементы:
var vegiesList = (from veg in xDoc.Descendants("vegetable")
select new Vegetable()
{
Name = veg.Element("name").Value,
Recipes = (from re in veg.Elements("recipe")
select new Recipe(re.Element("name").Value, re.Element("FilePath").Value)).ToList()
})
.ToList();
тогда для вашей структуры классов:
class Vegetable
{
public string Name { get; set; }
public List<Recipe> Recipes { get; set; }
}
class Recipe
{
public Recipe(string name, string path)
{
Name = name; Path = path;
}
public string Name { get; set; }
public string Path { get; set; }
}
vegiesList.ForEach(veg => comboBox1.Items.Add(veg.Name));
//You can select its property here depending on what property you want to add on your `ComboBox`