0

I'm trying to implement some code whereby I get the parent of the clicked toolstipmenuitem upto the root. If I query openly I eventually get a null exception from the one after the last parent, as you may expect where there is no parent to parent to get the parent of :

ToolStripMenuItem miOwnerItem = (ToolStripMenuItem)(mi.GetCurrentParent() as ToolStripDropDown).OwnerItem;

I've tried, unsuccessfully, below to implement a try catch and am wondering if anyone knows the best way to handle this null exception when querying for the OwnerItems.

    private void MenuClick2(object sender, EventArgs e)
    {
        //Click event begins by setting up variables and bringing in the sender as a menu item
        MenuResultsString.Visible = false;
        MenuResultsString.Text = "";
        ToolStripMenuItem mi = (ToolStripMenuItem)sender;
        string WhatClicked = mi.ToString();
        ToolStripMenuItem miOwnerItem = (ToolStripMenuItem)(mi.GetCurrentParent() as ToolStripDropDown).OwnerItem;
        string WhatClicked1up = miOwnerItem.ToString();
        string WhatClicked2up = "";
        string WhatClicked3up = "";
        string WhatClicked4up = "";
        string WhatClicked5up = "";
        float howDeep = 1;
        try
        {
            ToolStripMenuItem miGrandpapaOwnerItem = (ToolStripMenuItem)(miOwnerItem.GetCurrentParent() as ToolStripDropDown).OwnerItem;
            WhatClicked2up = miGrandpapaOwnerItem.ToString();
            howDeep = 2;
            try
            {
                ToolStripMenuItem miGreatGrandpapaOwnerItem = (ToolStripMenuItem)(miGrandpapaOwnerItem.GetCurrentParent() as ToolStripDropDown).OwnerItem;
                WhatClicked3up = miGreatGrandpapaOwnerItem.ToString();
                howDeep = 3;
                CSMorWhut = IsThisTheSystemMenu(WhatClicked3up);
                try
                {
                    ToolStripMenuItem miGreatestGrandpapaOwnerItem = (ToolStripMenuItem)(miGreatGrandpapaOwnerItem.GetCurrentParent() as ToolStripDropDown).OwnerItem;
                    WhatClicked4up = miGreatestGrandpapaOwnerItem.ToString();
                    howDeep = 4;
                    try
                    {
                        ToolStripMenuItem miAncestralGrandpapaOwnerItem = (ToolStripMenuItem)(miGreatestGrandpapaOwnerItem.GetCurrentParent() as ToolStripDropDown).OwnerItem;
                        WhatClicked4up = miGreatestGrandpapaOwnerItem.ToString();
                        howDeep = 5;
                    }
                    catch (Exception f)
                    {

                    }
                }
                catch (Exception f)
                {
                    
                }
            }
            catch (Exception f)
            {
                
            }
        }
        catch (Exception f)
        {
            
        }
  }

Below is a copy of my exception:

 System.NullReferenceException
 HResult=0x80004003
  Message=Object reference not set to an instance of an object.
  Source=Solution
  StackTrace:
   at Solution.App.MenuClick2(Object sender, EventArgs e) in E:\C02\Development\Visual Studio 2019\Source\Repos\Solution\App.cs:line 523

Any guidance would be greatly appreciated.

  • 1
    You can start by checking for null (`if (miOwnerItem == null)` ...), and then you decide what to do in case of a null. – Alessandro D'Andria May 03 '21 at 08:49
  • The problem I have is the way the below is build: ToolStripMenuItem miGreatestGrandpapaOwnerItem = (ToolStripMenuItem)(miGreatGrandpapaOwnerItem.GetCurrentParent() as ToolStripDropDown).OwnerItem; miGreatGrandpapaOwnerItem in the above would not be null, but the forming miGreatestGrandpapaOwnerItem would fail as for example if we use VS as an example, if I've gone File > Exit. The first would be Exit, the second would be File, the third would fail with the exception above – CO2 Software May 03 '21 at 09:13
  • As my problem was it was finishing its process too early because of a string match in another function, I added another parameter to the other function with a substring check on the one that has just called it, so essentially the same as what you were saying but using the logic check ahead of the function throwing the exception. Thanks for your response. – CO2 Software May 03 '21 at 10:23

1 Answers1

0

You can replace all of that with a loop to get a List<ToolStripMenuItem> contains the OwnerItem branch of a clicked item and break when the property returns null. The indices of the items are the levels (howDeep).

private void MenuClick2(object sender, EventArgs e)
{
    var tsmi = sender as ToolStripMenuItem;
    var tsmiOwnerItem = tsmi.OwnerItem;
    var tsmItems = new List<ToolStripMenuItem>();

    tsmItems.Add(tsmi);

    while (tsmiOwnerItem != null)
    {
        tsmItems.Insert(0, (ToolStripMenuItem)tsmiOwnerItem);
        tsmiOwnerItem = tsmiOwnerItem.OwnerItem;
    }

    for (var i = 0; i < tsmItems.Count; i++)
        Console.WriteLine($"Level {i:00} {tsmItems[i].Text}");
}

Note, no need for the expensive exception handlers here.

Side Notes

  1. Use generic exceptions whenever possible. If you expect dereferencing null objects references, then catch NullReferenceException. Read Catching specific vs. generic exceptions in c# for more.
  2. float howDeep = 1;. Its not possible for example to have a level 1.5. So use integral value type instead. i.e. int howDeep = 1;.
dr.null
  • 4,032
  • 3
  • 9
  • 12