Trying to query with Linq and display in DataGridView
I'm trying to display three columns in a DataGridView. Here is a sample of my XML:
<root>
<string id = "STRING_ID">
<node1> Some data </node1>
<node2>
<type>data</type>
</node2>
<Translations>
<language name="ARABIC">
<value>Some data</value>
<date_last_changed>7-4-2011</date_last_changed>
</language>
<language name="CHINESE">
...
...
</Translations>
</string>
<string id = "...">
...
...
The first column I want to display is the string id, an attribute value.
The second column I want to display is the <value>
data for each string
where <language name>
is equal to ENGLISH_US
.
The third column I want to display is the <value>
data for each string
where <language name>
is equal to the currently selected item in a ComboBox (populated with the names of each of the languages).
This is my Linq query at the moment:
var query_Id = from va in xdoc.Descendants("language")
where va.Attribute("name").Value == ("ENGLISH_US")
select new
{
StringID = va.Parent.Parent.Attribute("id").Value,
English = va.Element("value").Value,
Custom = <incomplete>
};
The problem with this is that while this gives me the first two columns, I cannot think of a way to get the third. In essence, I am searching for a solution that looks something like several selects based on things like WHERE language nam开发者_如何学Pythone = "VALUE"
etc. Something simple.
This should work. (You might want to add some error checking on the SingleOrDefault
)
var query = from va in xdoc.Descendants("language")
select new
{
StringID = va.Parent.Parent.Attribute("id").Value,
Language = va.Attribute("name").Value,
LanguageData = va.Element("value").Value,
};
var query2 = from x in query
group x by x.StringID into xg
select new
{
StringID = xg.Key,
English = xg.SingleOrDefault(x => x.Language == "ARABIC").LanguageData,
Custom = xg.SingleOrDefault(x => x.Language == otherLanguage).LanguageData,
};
Since you want a list of items per string keep that as your outer sequence in Linq and then work from there. You can use nested queries to pickup values within a particular item.
For example, if you know for sure that there is only one of each language id then you can use something like this, but it will fail if the language id is used twice in particular string.
string customLangId = ...
var results = from s in doc.Descendants("string")
let vs = s.Descendants("language")
.ToDictionary(l => (string)l.Attribute("name"), l => (string)l.Element("value"))
select new
{
StringID = (string)s.Attribute("id"),
English = vs.ContainsKey("ENGLISH_US") ? vs["ENGLISH_US"] : "(No Translation)",
Custom = vs.ContainsKey(customLangId) ? vs[customLangId] : ""
};
Another option would be to use let
for two inner queries. One for English and another for the custom language. You could end these with FirstOrDefault which would silently ignore any duplicate Ids at the expense of scanning the list of language values twice. You could also create a custom replacement for ToDictionary to provide the exact semantics you are looking for (i.e. keep first, keep last, or throw a custom exception).
精彩评论