I need to create a nested listview and found a great article on how to do it, but my situation is a bit different. I am a linq newbie and need a little help please :)
I need to get my data into a format similar in that article to work (on that link above, search for "Configuring the ListView" and see table right above it).
Here is my data:
Format Movie Name Price
DVD Star Wars 12.99
DVD Star Wars II 13.99
Blue-Ray Star Wars 15.99
Blue-Ray Star Wars II 17.99
Here is what I have, which isn't really that close, but it is as far as I could get:
var MoviesToBuy = from Movie in dtMovieListDetails.AsEnumerable()
//join MovieDetails in dtMovieListDetails.AsEnumerable() on (string)Movie["ID"] equals (string)MovieDetails["ID"]
group Movie by new
{
Format = Movie["Format"],
Movies = Movie
} into grp
select new
{
Format = (string)grp.Key.Format,
Movies = grp.Key.Movies
};
MoviesToBuy = MoviesToBuy.OrderBy(p => p.Format);
lvwAmazonMovieGroup.DataSource = MoviesToBuy.ToList();
lvwAmazonMovieGroup.DataBind();
I have 3 specific issues/questions:
1.) What I have doesn't work. Since my second column in the group equates to all rows, no actual group is created.
2.) Despite prior issue, I am also getting "Data source is an invalid type. It must be either an IListSource, IEnumerable, or IDataSource" error. In this case, the Movies column is being created as a DataRow datatype. Not sure if that is what is creating the problem. Can I cast on that field somehow?
3.) how can I sort on the fields in the movies. I.e. in the end I want the data to be sorted by Format then Movie Name so the nested list view looks like this:
Blue-Ray
Star Wars 12.99
Star Wars II 13.99
DVD
Star Wars 15.99
Star Wars II 17.99
Any points are greatly appreciated!
Thanks in advance,
Chad
I was thinking you could start with the following, adjusting for the proper variable names and AsEnumerable(), etc.
It orders your movies as you want and puts them in a nested structure as you requested:
var moviesToBuy = from movie in dtMovieListDetails
orderby movie.Format, movie.Price
group movie by movie.Format into grp
select new
{
Format = grp.Key,
Movies = grp.Select (g => new { MovieName = g.MovieName, Price = g.Price })
};
Here's an example program that implements the above query.
Try something like this:
var res = from m in movies
group m by m.Format into grouped
orderby grouped.Key
select new
{
Format = grouped.Key,
Movies = grouped.AsEnumerable().OrderBy(x => x.MovieName)
};
Alternatively
var res = from m in movies
orderby m.MovieName
group m by m.Format into grouped
orderby grouped.Key
select new
{
Format = grouped.Key,
Movies = grouped.AsEnumerable()
};
Using this seed data:
var movies = new[] {
new Movie { Format = "DVD", MovieName = "SW1"},
new Movie { Format = "Blue-ray", MovieName = "SW1"},
new Movie { Format = "DVD", MovieName = "SW2"},
new Movie { Format = "Blue-ray", MovieName = "SW2"},
new Movie { Format = "DVD", MovieName = "RF"}
};
Produced:
Format: Blue-ray
Movie: SW1
Movie: SW2
Format: DVD
Movie: RF
Movie: SW1
Movie: SW2
Just for completness, I used this code to generate the previous list
foreach (var item in res)
{
Console.WriteLine("Format: " + item.Format);
foreach (var item2 in item.Movies)
{
Console.WriteLine("\tMovie: " + item2.MovieName);
}
}
Related
i have two list list content listearticle and this the code of this list:
model = (
from article in db.Article
select new
{
ID = article.ID,
ARTICLE = article.CODEARTICLE,
PRIX= article.PRIX,
STOCK=article.STOCK,
IMAGE = article.Image,
DESCRIPTION= article.REFERENCE,
});
and another content list convention and this is the code :
var query = (
from article in db.convention
select new
{
ID = article.ID,
ARTICLE = article.CODEARTICLE,
PRIX = article.Prix,
});
i want to have a list listarticleconvention like this:
foreach (dynamic aa in model)
{
foreach (dynamic aa1 in list1)
{
if (aa.ARTICLE == aa1.ARTICLE)
{
aa.PRIXVHT = aa1.PRIXVHT;
}
}
}
Can someone help me to edit PRIXVHT when this article exist in list1 and thank you for your help
the error apperead is Additional information: Property or indexer '<>f__AnonymousType3.PRIXVHT' cannot be assigned to -- it is read only
i know that's just read read only but i need to edit it how can i do it
N.B/i have to use a form like that i mean something like foreach in this two list
You can join db.Article to db.convention and then select article.PRIX if query.PRIX is null.
from articleA in db.Article
join articleC in db.convention on articleC.ID equals articleA.ID into temp
from query in temp.DefaultIfEmpty()
select new
{
ID = articleA.ID,
ARTICLE = articleA.CODEARTICLE,
PRIX = (query== null ? articleA.PRIX : query.PRIX),
STOCK = articleA.STOCK,
IMAGE = articleA.Image,
DESCRIPTION = articleA.REFERENCE,
});
I am trying to add one list into another but it is giving me error of The best overloaded method match for 'System.Collection.Generic.List.AddRange(System.Collections.Generic.IEnumerable)' has some invalid arguments
My code is:
public ActionResult RegisteredEvent(string Cno)
{
if (Request.IsAjaxRequest())
{
List<tblEvent> eventlist = new List<tblEvent>();
List<RegisteredEvent> list = new List<RegisteredEvent>();
var db = new clubDataContext();
int[] eventIds = (from m in db.EventRegistrations where m.Cno == Cno select m.Event_Id).ToArray();
int i = 1;
foreach (var item in eventIds)
{
list = (from m in db.tblEvents
where item.Equals(m.EventId)
select new RegisteredEvent()
{
id = m.EventId,
caption = m.Caption,
description = m.Description,
date = m.Date.ToString()
}).ToList();
eventlist.AddRange(list); //Here I am getting error
}
ViewBag.eventDetail = eventlist;
return PartialView("RegisteredEvent");
Simply speaking, you can only concatenate lists of the same type.¹
eventlist is a List<tblEvent>
list is a List<RegisteredEvent>
¹ This is not entirely correct: Since IEnumerable is covariant, it is actually possible to add entries of a List<S> to a List<T>, if S is a subtype of T.
The T in List<T> needs to have the same type or inherent from the same base type
List<RegisteredEvent> eventlist
List<RegisteredEvent> list
or
List<tblEvent> eventlist
List<tblEvent> list
You can use IEnumerable.Select as this (I don't know the structure of tblEvent, so adapt this at your code.
eventlist.AddRange(list.Select(x => new tblEvent{ id = x.id, caption = x.caption, ... }));
But the best way is to create directly a tblEvent
//the list sent to View
eventlist = (from m in db.tblEvents
where item.Equals(m.EventId)
select new tblEvent() //here
{
id = m.EventId,
caption = m.Caption,
description = m.Description,
date = m.Date.ToString()
}).ToList();
Group data in C#, I have parsed the html file and get all the data on it, now I want to group them as following:
Those lines which are selected are the parent and contain the following childs, the code that I'm working on is here:
var uricontent = File.ReadAllText("TestHtml/Bew.html");
var doc = new HtmlDocument(); // with HTML Agility pack
doc.LoadHtml(uricontent);
var rooms = doc.DocumentNode.SelectNodes("//table[#class='rates']").SelectMany(
detail =>
{
return doc.DocumentNode.SelectNodes("//td[#class='rate-description'] | //table[#class='rooms']//h2 | //table[#class='rooms']//td[#class='room-price room-price-total']").Select(
r => new
{
RoomType = r.InnerText.CleanInnerText(),
});
}).ToArray();
the RoomType contains the data which is parsed by HTML AgilityPack, how can I group them by the Name like Pay & Save , Best Available Room Only ...
HTML File is here : http://notepad.cc/share/g0zh0TcyaG
Thank you
Instead of doing union of 3 XPath queries, then trying to group them back by "Rate Description" (aka by element : <td class="rate-description">), you can do it another way around.
You can base your LINQ selection by "Rate Description", then in projection part, get all room types and room rates under current "Rate Description" using relative XPath :
var rooms =
doc.DocumentNode
.SelectNodes("//table[#class='rates']//tr[#class='rate']")
.Select(r => new
{
RateType = r.SelectSingleNode("./td[#class='rate-description']")
.InnerText.CleanInnerText,
RoomTypes = r.SelectNodes("./following-sibling::tr[#class='rooms'][1]//table[#class='rooms']//h2")
.Select(s => new
{
RoomType = s.InnerText.CleanInnerText,
Rate = s.SelectSingleNode(".//parent::td/following-sibling::td[#class='room-price room-price-total'][1]")
.InnerText.CleanInnerText
}).ToArray()
}).ToArray();
Notice period at the beginning of some XPath queries above. That tells HtmlAgilityPack that the query is relative to current HtmlNode. The result is about like this :
I am coding in Microsoft Visual Studio 12 in ASP.net using c# and a noob at it.
This is what csv file looks like
ID, Engine Type, Car
111,vtec, 1
131,vtec, 1
157,boxer,1
148,boxer,1
167,vtec,1
158,,0
107,,0
ID should be a generic autonumber, Engine Type should be a type string and I don't know what Car should because it consists off 1's and 0's representing Boolean. This means that 1-customer has a car and 0 means that customer doesn't have a car.
This is how i create a list out of it.
var testingobject = (
from line in File.ReadAllLines("testing.csv").Skip(0)
let parts = line.Split(',')
select new
{
ID = parts[0],
Engine_Type = parts[1],
Car = parts[2] //should i put int32.parse(parts[2]) here
).ToList();
I create a simple array which consists of ID,Engine Type,Car convert it to a list using ToList() and then bind it to a dropdownlist, using this code:
string[] testingddl = new string[] { "ID", "Engine Type", "Car" };
List<String> mytestinglist = testingddl.ToList();
var mytestin = from m in mytestinglist
select m;
DropDownList1.DataSource = mytestin.AsEnumerable();
DropDownList1.DataTextField = "";
DropDownList1.DataValueField = "";
DropDownList1.DataBind();
User selects Car and should give me the a chart that has engine type in x-axis and total on y-axis.
The Problem: The column consists of 1's and 0's meaning whether the customer has a car (1) or doesnt (0).
I would like to view how many users have different types of engines types and bind it to a, say a column chart. So the data should display on the x-axis, engine type and y-axis should have the total. according to the data, there are 3 vtecs and 2 boxers. So vtecs represent a column with 3 total and boxers with 2.
I use this linq query and the following chart binding code.
if (tempval == "Car")// this is the current selected dropdown list value
{
var myfavitems = testingobject.Where(a => a.Car == "1").ToList();
foreach (var t in myfavitems.GroupBy(a => a.Engine_Type))
{
Series Series1 = new Series();
Chart1.Series.Add(Series1);
Chart1.Series[1].Points.AddXY(t.Key.ToString(), t.Count().ToString()).ToString();
Chart1.DataSource = myfavitems.AsEnumerable();
Chart1.Series[1].XValueMember = "Group Equipment Type";
Chart1.Series[1].YValueMembers = "Software";
Chart1.DataBind();
// ...??
The error comes at the point where I am reading my columns from the csv files. The error says Format exception was unhandled by user code: Input string was not in a correct format
select new
{
ID = parts[0],
Engine_Type = parts[1],
Car = Int32.Parse(parts[2])
}
I dont know what is wrong with that statement. Could someone please help me out.
You will want to have a class like this:
public class CarClass {
public int Id { get; set; }
public string Engine { get; set; }
public int Car { get; set; }
}
And then do something like:
var car_collection =
from line in File.ReadAllLines("your_csv_name.csv").Skip(1)
let parts = line.Split(',')
select new CarClass()
{
Id = Int32.Parse(parts[0]),
Engine = parts[1],
Car = Int32.Parse(parts[2])
};
var listy = car_collection.ToList();
Otherwise, notice the '{ }' and the '( )' , because yours don't match:
var car_collection =
(from line in File.ReadAllLines("your_csv_name.csv").Skip(1)
let parts = line.Split(',')
select new CarClass()
{
Id = Int32.Parse(parts[0]),
Engine = parts[1],
Car = Int32.Parse(parts[2])
}).ToList();
That should solve your problem with the error
If your header row is in CSV file then
Car = Int32.Parse(parts[2])
is trying to parse "Car" to Int32.
Try reading file with:
File.ReadAllLines("testing.csv").Skip(1)
to skip header row.
I have the following XML and want to return all "schools" children but I only get the first one. (jeffersion/08.36) I looked high and low and banged my head. What am I missing?
<users>
<user>
<role>janitor</role>
<schools>
<school_name>jefferson</school_name>
<keycode>80.36</keycode>
<school_name>mainline</school_name>
<keycode>64.36</keycode>
<school_name>south side</school_name>
<keycode>31</keycode>
</schools>
</user>
</users>
This is only returning the first record.
var results= from schools in myXmlDoc.Descendants("schools")
select new
{
SchoolName = schools.Element("school_name").Value,
KeyCode = schools.Element("keycode").Value
};
I've also tried:
var results= (from schools in myXmlDoc.Descendants("schools")
select new
{
SchoolName = schools.Element("school_name").Value,
KeyCode = schools.Element("keycode").Value
}.ToList();
This gets the values BUT only for the first school:
var schools = (from c in xml.Descendants("user")
select new
{
Name = c.Element("role").Value,
Fields = c.Elements("schools")
.Select(f => new
{
SchoolName = f.Element("school_name").Value,
Keycode = f.Element("keycode").Value
}).ToArray()
}).ToList();
You only have one <schools> element in your source, which is why only one entry is being returned. The XML isn't particularly nicely structured - it would be good to have a <school> element containing each school_name/keycode pair. But assuming you have to live with it, the following should work:
var results= from school in myXmlDoc.Descendants("school_name")
select new
{
SchoolName = school.Value,
KeyCode = school.ElementsAfterSelf("keycode").First().Value
};
This may be helpful:
var result = from c in XElement.Load("Student.xml").Elements("schools")
select c ;
// Execute the query
foreach (var students in result )
{
//do something
}