Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/263.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 获取指定父级的所有直接子级_C#_Linq - Fatal编程技术网

C# 获取指定父级的所有直接子级

C# 获取指定父级的所有直接子级,c#,linq,C#,Linq,我有一个名为GetMenuItems的方法,它返回继承人的体系结构结果。以下是实施方案: public static ObservableCollection<MenuItem> GetMenuItems() { XDocument xDoc = XDocument.Load(DirectoryPaths.DataDirectory_General + "MenuItems.xml"); return LoadMenuItems(xDoc.Descendants("M

我有一个名为GetMenuItems的方法,它返回继承人的体系结构结果。以下是实施方案:

public static ObservableCollection<MenuItem> GetMenuItems()
{
    XDocument xDoc = XDocument.Load(DirectoryPaths.DataDirectory_General + "MenuItems.xml");
    return LoadMenuItems(xDoc.Descendants("MenuItem"));
}

private static ObservableCollection<MenuItem> LoadMenuItems(IEnumerable<XElement> menuItems)
{
    return new ObservableCollection<MenuItem>(
        menuItems.Select(
            x => new MenuItem()
            {
                Id = Convert.ToDouble(x.Attribute("Id").Value),
                Name = x.Element("Name").Value,
                ImageData = x.Elements("ImageData").Any() ? x.Element("ImageData").Value : "",
                Angle = x.Elements("Angle").Any() ? Convert.ToDouble(x.Element("Angle").Value) : 0,
                ScaleX = x.Elements("ScaleX").Any() ? Convert.ToInt32(x.Element("ScaleX").Value) : 0,
                ScaleY = x.Elements("ScaleY").Any() ? Convert.ToInt32(x.Element("ScaleY").Value) : 0,
                ShortcutKey = x.Elements("ShortcutKey").Any() ? x.Element("ShortcutKey").Value : "",
                Background = x.Elements("Background").Any() ? x.Element("Background").Value : "#FF000000",
                MouseOver = x.Elements("MouseOver").Any() ? x.Element("MouseOver").Value : "#FF696969",
                menuItem = x.Elements("MenuItem").Any() ? LoadMenuItems(x.Elements("MenuItem")) : null
            }

        )

     );

}
公共静态ObservableCollection GetMenuItems()
{
XDocument xDoc=XDocument.Load(directorypath.DataDirectory_General+“MenuItems.xml”);
返回LoadMenuItems(xDoc.substands(“MenuItem”);
}
私有静态ObservableCollection LoadMenuItems(IEnumerable menuItems)
{
返回新的ObservableCollection(
菜单项。选择(
x=>新菜单项()
{
Id=Convert.ToDouble(x.Attribute(“Id”).Value),
名称=x.Element(“名称”).值,
ImageData=x.Elements(“ImageData”)。任意()?x.Element(“ImageData”)。值:“”,
Angle=x.Element(“Angle”).Any()?转换为双(x.Element(“Angle”).Value):0,
ScaleX=x.Element(“ScaleX”).Any()?转换.ToInt32(x.Element(“ScaleX”).Value):0,
ScaleY=x.Element(“ScaleY”).Any()?转换.ToInt32(x.Element(“ScaleY”).Value):0,
ShortcutKey=x.Elements(“ShortcutKey”).Any()?x.Element(“ShortcutKey”)。值:“”,
Background=x.Elements(“Background”).Any()?x.Element(“Background”)。值:“#FF000000”,
MouseOver=x.Elements(“MouseOver”).Any()?x.Element(“MouseOver”)。值:“#FF696969”,
menuItem=x.Elements(“menuItem”)。Any()?LoadMenuItems(x.Elements(“menuItem”):null
}
)
);
}
现在我想得到一个特定父母的所有直接子女

为了更清楚,让我举一个例子:

假设我想获取MenuItem的所有直接子MenuItem,其
Id=1


请注意,我需要使用GetMenuItems()方法,因为我不允许访问这些XML文件。

您应该将任务分为两部分:

  • 查找具有特定ID的菜单
  • 得到它的孩子
后者很简单-您只需使用
menuItem
属性,该属性最好命名为
Children
或类似的名称

在做了一个重要的更改之后,我将通过递归处理第一部分。如果没有元素,
Children
属性将不为null,只需将其设置为空集合即可:

Children = LoadMenuItems(x.Elements("MenuItem")
这样,您可以非常轻松地检查所有子项,即使没有任何子项,也不需要任何空性检查。通常,将缺少项表示为空集合比表示为空引用更容易

因此,要通过ID递归查找菜单项,我将使用:

// TODO: Change the ID type from double to almost anything else. double is a
// *terrible* type to use for IDs.
public MenuItem FindMenuItemById(MenuItem item, double id)
{
    return item.Id == id ? item : item.Children
                                      .Select(x => FindMenuItemById(x, id))
                                      .Where(found => found != null)
                                      .FirstOrDefault();
}
如果没有这样的菜单项,它将返回
null
。然后您可以使用:

if (item != null)
{
    var children = item.Children;
    ...
}
另外,使用
XElement
上的转换运算符和空合并运算符可以更简单地转换其他属性

// Again, change this! Don't use double!
Id = (double) x.Attribute("Id"),
Name = (string) x.Element("Name"),
ImageData = (string) x.Element("ImageData") ?? "",
Angle = (double?) x.Element("Angle") ?? 0d,
ScaleX = (double?) x.Element("ScaleX") ?? 0d,
ScaleY = (double?) x.Element("ScaleY") ?? 0d,
ShortcutKey = (string) x.Element("ShortcutKey") ?? "",
Background = (string) x.Element("Background") ?? "#FF000000",
MouseOver = (string) x.Element("MouseOver") ?? "#FF696969",

那么
menuItem
是儿童的集合吗?(这是一个非传统的名称,它使用
null
而不是一个空集合来表示缺少孩子,这实际上是毫无帮助的…@JonSkeet Yes menuItem是一个孩子的集合,我怎么能有一个空集合?我会在我的答案中添加它。回答得很好。我仍然想问两个问题。1) 为什么我不应该对Id使用双数据类型。我这样问是因为我在XML文件中有层次结构,所以我的Id是1,1.1,1.2,2,3,3.1。。。。。。。。。。2) 如果我只想得到顶级物品,那我该怎么办?谢谢你的帮助。@Vishal:关于这两个部分,想一想——第3项的第10个孩子长什么样?我怀疑是“3.10”,与“3.1”的值相同。基本上,菜单项ID不是小数。我建议你用字符串代替。对于获取顶级项目,这就是
GetMenuItems()
所提供的,不是吗?是的,我理解使用double是危险的,我希望使用字符串。GetMenuItems()返回包括子项在内的所有项。我不想要孩子。@Vishal:啊,我错过了后代的使用。这就是问题所在—在找到父节点后,使用
元素
—我不知道XML是什么样子,所以我不知道它到底是什么样子。例如,它可能是
xDoc.Root.Elements(“MenuItem”)
。谢谢。它现在工作得很好。我将
GetMenuItems
方法中的
xDoc.degents(“MenuItem”)
更改为
xDoc.Element(“MenuItem”).Elements(“MenuItems”)