尝试使用Linq进行查询并在DataGridView中显示

时间:2011-07-29 15:53:01

标签: c# .net xml linq

我正在尝试在DataGridView中显示三列。 以下是我的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 = "...">
   ...
   ...

我要显示的第一列是字符串id,属性值。 我要显示的第二列是每个<value>的{​​{1}}数据,其中string等于<language name>。 我要显示的第三列是每个ENGLISH_US的{​​{1}}数据,其中<value>等于ComboBox中当前选定的项目(填充了每种语言的名称)。

这是我目前的Linq查询:

string

这个问题是,虽然这给了我前两列,但我想不出有办法获得第三列。从本质上讲,我正在寻找一个基于<language name>之类的东西看起来像几个选择的解决方案。简单。

2 个答案:

答案 0 :(得分:2)

这应该有效。 (您可能希望在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,
               };

答案 1 :(得分:1)

由于您需要每个字符串的项目列表,请将其作为Linq中的外部序列,然后从那里开始工作。您可以使用嵌套查询来获取特定项目中的值。

例如,如果您确定每个语言ID只有一个,那么您可以使用类似的东西,但如果在特定字符串中使用两次语言ID,它将失败。

    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] : ""
                            };

另一种选择是使用let进行两次内部查询。一个用于英语,另一个用于自定义语言。您可以使用FirstOrDefault结束这些操作,它会以两次扫描语言值列表为代价,默默地忽略任何重复的ID。您还可以为ToDictionary创建自定义替换,以提供您要查找的确切语义(即先保留,保留最后或抛出自定义异常)。