Get all the direct Children of a specified Parent

I have a method called GetMenuItems which returns Heirarchical results. Here is the implementation:

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
            }

        )

     );

}

Now I want to get all the direct children of a specific Parent.

To make it more clear let me give an example:

Suppose I want to get all the direct children MenuItems of MenuItem whose Id = 1.

Please note that I need to use GetMenuItems() method as I am not allowed to access those XML Files.

Jon Skeet
people
quotationmark

You should split your task into two parts:

  • Finding the menu with a particular ID
  • Getting its children

The latter is simple - you just use the menuItem property, which would be better named Children or something similar.

I'd tackle the first part by recursion - after making one important change. Instead of the Children property being null if there are no elements, just let it be an empty collection:

Children = LoadMenuItems(x.Elements("MenuItem")

That way, you can check all the children very easily, even if there aren't any - without any nullity checks. Generally, it's easier to represent a lack of items as an empty collection rather than a null reference.

So, to recursively find a menu item by ID, I'd use:

// 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();
}

That will return null if there's no such menu item. Then you can just use:

if (item != null)
{
    var children = item.Children;
    ...
}

As an aside, your other properties can be converted much more simply using the conversion operators on XElement and the null-coalescing operator

// 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",

people

See more on this question at Stackoverflow