Saving values into List in a class by using LINQ - c#

I have a class Item with a string List ImagesUrl property:
public class Item
{
string Name { get; set; }
List<string> ImagesUrl { get; set; }
..
}
And I want to parse a XML file and save each node item into var items. In node item there are nodes img1, .. , img5 and right these I want to save into the Img property by using LINQ command like this:
var items = from item in xmlDocument.Descendants("item")
select new Item
{
Name = item.Element("name").Value,
ImagesUrl = item.Element("img1").Value, //....?
..
};
How you can see, I don't know how I could save the img1..5 values in LINQ. Could someone help me?

var items = from item in xmlDocument.Descendants("item")
select new Item
{
Name = item.Element("name").Value,
ImagesUrl = Enumerable.Range(1,5).Select(x => item.Element("img"+x).Value).ToList();
};
Code is self-explanatory here.

Universal solution independent on count of imgX elements
var items = from item in Xml.Descendants("item")
select new Item
{
Name = item.Element("name").Value,
ImagesUrl = item.Elements()
.Where(e => e.Name.LocalName.StartsWith("img"))
.Select(e => e.Value)
.ToList()
};

Related

How can I create a list inside a list with a foreach in c# ?

In other words I need all the elements of list "Categories" to be the "Parent" and elements of list "commodities" be the children.
Example
public string GetCommodities()
{
List<dynamic> categories = new List<dynamic>();
List<dynamic> commodities = new List<dynamic>();
foreach (var comcat in QuickQuoteRepo.CommodityCategories.All().OrderBy(o => o.Order))
{
categories.Add(new
{
comcat.Category,
});
foreach (var com in comcat.Commodities.OrderBy(o => o.Name))
{
commodities.Add(new
{
com.Name,
});
}
}
var response = new JavaScriptSerializer().Serialize(commodities);
return response;
}
And see if it's possible to all commodities names inside each category, within this foreach.
I tried adding a dynamic list such as:
dynamic listOfElements = new { CAT = categories, COMM = commodities };
But it does't return elemnts as parents or dependency of categories. Is the same as adding
commodities.Add(new
{
comcat.Category,
com.Name,
});
public string GetCommodities()
{
List<dynamic> categoryCommodityList = new List<dynamic>();
foreach (var comcat in QuickQuoteRepo.CommodityCategories.All().OrderBy(o => o.Order))
{
var allCommodities = comcat.Commodities.OrderBy(o => o.Name).Select(com => com.Name).ToList();
categoryCommodityList.Add(new { Catagory = comcat.Category, Items = allCommodities } );
}
return new JavaScriptSerializer().Serialize(categoryCommodityList);
}
You class structure does not support parent-child relationships. I mean, if what you want is that each Category holds a list of commodities, then you would need something like this:
var result = from c in comcat
select new { Category = c, Commoddities = c.Commoddities};
This will return a hierarchy of Categories including all Commodities underneath it.
If you are just receiving a flat data set, then you need something like this:
var result = from c in comcat
select new { Category = c,
Commoddities = c.Where(x=>x.Category.Name == c.Name).Select(x=>x.Commodity) };
Hopefully you get the idea...

Set Attribute to ListItem in Linq Query

From list i am populating ListItem for dropdown list.
var list = LoadList();
var listitems = list.Select(l => new ListItem
{
Value = l.Id,
Text = l.Description
Attributes ????
}).ToList();
On the Linq query I want to add attribute. Attributes.Add() method is not accessible. Any idea?
From MSDN, the Attributes property is read only:
[BrowsableAttribute(false)]
public AttributeCollection Attributes { get; }
so you will not be able to do it using the object initialisers.
You could do this by doing something like:
var listitems = list.Select(l => { var li = new ListItem
{
Value = l.Id,
Text = l.Description
}; li.Attributes.Add(....); return li; ).ToList();

Parse Hierarchial Linq to XML

I am trying to parse this data:
<Product>
<ProductName>Climate Guard</ProductName>
<Tag>ClimateGuard</Tag>
<SupportPage>~/Support/ClimateGuard.aspx</SupportPage>
<ProductPage>~/Products/ClimateGuard.aspx</ProductPage>
<ProductCategories>
<ProductCategory>Climate Guard</ProductCategory>
<PartNumbers>
<PartNumber Primary="true">CLIMATE GUARD</PartNumber>
<PartNumber>CLIMATEGUARD LT</PartNumber>
<PartNumber>CLIMATE GUARD STARTER KIT</PartNumber>
<PartNumber>SENSOR MODULE</PartNumber>
<PartNumber>SWCH INP MODULE</PartNumber>
<PartNumber>TEMP SENSOR</PartNumber>
<PartNumber>HUMIDITY SENSOR</PartNumber>
<PartNumber>DOOR CONTACT</PartNumber>
<PartNumber>MOTION SENSOR</PartNumber>
<PartNumber>FLOOD DETECTOR</PartNumber>
<PartNumber>SMOKE DETECTOR</PartNumber>
<PartNumber>TILT SENSOR</PartNumber>
<PartNumber>SENSOR CABLE</PartNumber>
<PartNumber>PWR INP CABLE</PartNumber>
<PartNumber>100FT 2-WIRE</PartNumber>
<PartNumber>RJ25 COUPLER</PartNumber>
</PartNumbers>
</ProductCategories>
<Downloads>
<Download>
<Version>1.0.27</Version>
<Url>~/Files/Downloads/ClimateGuard_Firmware_1_0_27.bin</Url>
<Comment>Firmware</Comment>
</Download>
<Download>
<Version>1.0.6</Version>
<Url>~/Files/Downloads/ClimateGuard_BuiltInModule_1_0_6.bin</Url>
<Comment>Built-in Module</Comment>
</Download>
<Download>
<Version>1.0.2</Version>
<Url>~/Files/Downloads/ClimateGuard_SensorModule_1_0_2.bin</Url>
<Comment>Sensor Module</Comment>
</Download>
<Download>
<Version>1.0.0</Version>
<Url>~/Files/Downloads/ClimateGuard_SwitchInputModule_1_0_0.bin</Url>
<Comment>Switch Input Module</Comment>
</Download>
</Downloads>
</Product>
I am trying to get a List of part numbers, however, only the first appears:
Product Category Climate Guard
Part Number Climate Guard
What is wrong with my part numbers code:
public List<Products> GetProducts()
{
XElement myElement = XElement.Load(HttpContext.Current.Server.MapPath("~/App_Data/products.xml"));
var query = from a in myElement.Elements("Product")
select new Products
{
ProductName = a.Element("ProductName").Value,
Tag = a.Element("Tag").Value,
SupportPage = a.Element("SupportPage").Value,
ProductPage = a.Element("ProductPage").Value,
ProductCategories = from b in a.Elements("ProductCategories")
select new ProductCategories
{
ProductCategory = b.Element("ProductCategory").Value,
//PartNumbers = GetPartNumbers(myElement.Elements("Product").Elements("ProductCategories").Elements("PartNumbers").Elements("PartNumber"))
PartNumbers = from c in b.Elements("PartNumbers")
select new PartNumbers
{
PartNumber = c.Element("PartNumber").Value
}
},
Downloads = from bb in a.Elements("Downloads").Elements("Download")
select new Downloads
{
Comment = bb.Element("Comment").Value,
Url = bb.Element("Url").Value,
Version = bb.Element("Version").Value
},
};
return query.ToList();
}
All of the types (ProductName, Tag, etc.) are strings. PartNumbers is an IEnumerable.
Currently instead of getting collection of PartNumber element values, you are getting only element for their parent PartNumbers with value of first PartNumber child inside. If you want to have PartNumbers class instead of simple list of string values, then it should look like:
public class PartNumbers
{
// list instead of single value
public List<string> Numbers { get; set; }
}
And it should be parsed this way:
PartNumbers = new PartNumbers {
Numbers = b.Element("PartNumbers").Elements()
.Select(c => (string)c).ToList()
}
BTW why are you choosing so strange range variable names (b for ProductCategories elements, a for products, etc)? Also you can use simple List<string> to store part numbers (without creating class for that):
PartNumbers = b.Element("PartNumbers").Elements().Select(c => (string)c).ToList()
You may have forgotten the ToList() for ProductCategories, PartNumbers and Downloads.
public List<Products> GetProducts()
{
XElement myElement = XElement.Load(HttpContext.Current.Server.MapPath("~/App_Data/products.xml"));
var query = from a in myElement.Elements("Product")
select new Products
{
ProductName = a.Element("ProductName").Value,
Tag = a.Element("Tag").Value,
SupportPage = a.Element("SupportPage").Value,
ProductPage = a.Element("ProductPage").Value,
ProductCategories = (from b in a.Elements("ProductCategories")
select new ProductCategories
{
ProductCategory = b.Element("ProductCategory").Value,
//PartNumbers = GetPartNumbers(myElement.Elements("Product").Elements("ProductCategories").Elements("PartNumbers").Elements("PartNumber"))
PartNumbers = (from c in b.Elements("PartNumbers")
select new PartNumbers
{
PartNumber = c.Element("PartNumber").Value
}).ToList()
}).ToList(),
Downloads = (from bb in a.Elements("Downloads").Elements("Download")
select new Downloads
{
Comment = bb.Element("Comment").Value,
Url = bb.Element("Url").Value,
Version = bb.Element("Version").Value
}).ToList(),
};
return query.ToList();
}

How do I sort an ArrayList containing more than 1 parameter per object alphabetically?

Greetings (Don't know if the title makes sense)
I have an ArrayList which can contain a different amount of objects in it.
Example
private ArrayList items = new ArrayList();
var list = web.Lists[ListName];
items.Add(new { GroupName = value });
foreach (SPListItem item in list.Items)
{
items.Add(new { GroupName = value, ItemID = item.ID, ItemName = item.Name });
}
As you can see above, I have an object only containing GroupName and then an object containing GroupName, ItemID and ItemName
What I want to do is to sort all the items by their ItemName.
I have no issue sorting it when it's only one parameter, but when it's multiple parameters, I'm clueless. How do I do this?
EDIT: Sort before adding to the new arraylist
foreach(SPListItem item in list.Items.Cast<SPListItem>.OrderBy(i => i.Name))
{
items.Add(new { GroupName = value, ItemID = item.ID, ItemName = item.Name });
}
Newer EDIT:
If you just want an enumerable collection (without the arraylist, in which you cannot extract the items from easily), you could just use the LINQ Select operator.
var items = ist.Items.Cast<SPListItem>.OrderBy(i => i.Name).Select(i => new { GroupName = value, ItemID = i.ID, ItemName = i.Name });

Parse XML and populate in List Box

I'm a newbie to C#.
I want to develop C# List box in Windows Form. I found this link to be helpful.
But the input to the List box will be an XML of the following format:
<LISTBOX_ST>
<item><CHK></CHK><SEL>00001</SEL><VALUE>val01</VALUE></item>
<item><CHK></CHK><SEL>00002</SEL><VALUE>val02</VALUE></item>
<item><CHK></CHK><SEL>00003</SEL><VALUE>val03</VALUE></item>
<item><CHK></CHK><SEL>00004</SEL><VALUE>val04</VALUE></item>
<item><CHK></CHK><SEL>00005</SEL><VALUE>val05</VALUE></item>
</LISTBOX_ST>
The XML has to be parsed and should be populated in the list box. When particular item in the list is selected, it's CODE should be returned(i.e the value of SEL node).
Any pointers/suggestions as how to parse effectively and display in List.
The XML is coming from SAP and expecting to have around 300 to 400 records.
You could use Linq to XML to do it like this.
XDocument xmldoc = XDocument.Load(xmlStream);
var items = (from i in xmldoc.Descendants("item")
select new { Item = i.Element("SEL").Value, Value = i.Element("VALUE").Value }).ToList();
listBox1.DataSource = items;
listBox1.DisplayMember = "Item";
listBox1.ValueMember = "Value";
Using Linq-to-XML, you can do this:
public partial class item
{
public object CHK { get; set; }
public int SEL { get; set; }
public string VALUE { get; set; }
}
and somewhere in your code:
XDocument lbSrc = XDocument.Load("yourfile.xml");
List<item> _lbList = new List<item>();
foreach (XElement item in lbSrc.Descendants("item"))
{
_lbList.Add(new item { CHK= item.Element("CHK").Value,
SEL = Convert.ToInt32(item.Element("SEL").Value),
VALUE = item.Element("VALUE").Value });
}
and then assign that to your listbox:
lbYourListbox.DataSource = _lbList;
lbYourListbox.DisplayMember = "VALUE";
lbYourListbox.ValueMember = "SEL";
That should do it!

Categories

Resources