0

I have a ContextMenuStrip, at runtime I add new items to that ContextMenuStrip and I want to know how I can check if the ContextMenuStrip contains the item, if the same item is already in the ContextMenuStrip then dont add the item again. Only add items that are not in the ContextMenuStrip.

How can I do that?

public Form3()
{
    InitializeComponent();
    loginicon.ContextMenuStrip = contextMenuStrip1;
}

private void loginicon_Click(object sender, EventArgs e)
{
    cmd = new SqlCommand($"Select * from UserInfo where Username='{user}'");
    cmd.Connection = con;
    con.Open();
    SqlDataReader reader = cmd.ExecuteReader();
    while (reader.Read())
    {
        id = reader[3].ToString();
    }

    // contextMenuStrip1.Items.Contains(user);
    contextMenuStrip1.Items.Add(user);
    contextMenuStrip1.Items.Add(id);
    contextMenuStrip1.Items.Add("Logout");
    reader.Close();
    con.Close();
}

This is my code for that ContextMenuStrip.

Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
  • Since you known in advance how many items you're adding, add the items with empty text: `contextMenuStrip1.Items.Add("");`, so you can also add the event handlers in the same `Add()` method. Then, when you have the right text, add just that: `contextMenuStrip1.Items[0].Text = user; contextMenuStrip1.Items[1].Text = id`. If your ContextMenuStrip is already setup, avoid querying the database a second time (you can use a bool field, check the value of the first ContextMenuStrip Item, whatever). Btw, you can query just the `id` field and get its value with `ExcuteScalar()` – Jimi Aug 30 '20 at 18:11

3 Answers3

0

Im not sure, but you can use foreach loop to check all items

        foreach (ToolStripMenuItem contextMenuItem in contextMenuStrip1.Items)
        {
          contextMenuItem.Text.Contains("Whatever string");
        }

or else "for" loop. If you want to test only one of items

int thenumber_of_object_inside_contextstripmenu = 1;//the number of object
contextMenuStrip1.Items[thenumber_of_object_inside_contextstripmenu].Text.Contains("Whatever string");//should output true/false
micegan
  • 51
  • 4
  • Its not working as I am adding items at run time so first time there wont be any item so can't test the condition –  Aug 30 '20 at 18:57
0

This can be done, If I place the code at form_load event rather than button click

0

So all items in your context menu are unique. Keep a HashSet that remembers which menu items are already added.

In your form class:

private HashSet<MenuItem> addedMenuItems;

void MyForm
{
     InitializeComponents();
     List<MenuItem> menuItems = this.ContextMenu1.MenuItems.Cast<MenuItem>().ToList();
     this.addedMenuItems = new HashSet<MenuItem>(menuItems);
}

private bool IsMenuItemAdded(MenuItem menuItem)
{
    return this.addedMenuItems.Contains(menuItem);
}

private void AddMenuItem(MenuItem menuItem)
{

    if (!this.IsMenuItemAdded(menuItem))
    {
         this.ContextMenu1.MenuItems.Add(menuItem);
         this.AddedMenuItems.Add(menuItem);
    }
}
private void RemoveMenuItem(MenuItem menuItem)
{
    if (this.IsMenuItemAdded(menuItem))
    {
         this.ContextMenu1.MenuItems.Remove(menuItem);
         addedMenuItems.Remove(menuItem);
    }
}

The problem with this is that you can't prevent that others add menu items directly

Reusable Solution: make a MenuItemCollectionHandler

Create a class, that takes a Menu.MenuItemCollection (or if you want: a Menu), and that makes sure that you can only Add / Remove predefined items

class UniqueMenuItemCollectionHandler
{
    private HashSet<MenuItem> addedMenuItems;
    private MenuItemCollection menuItemCollection;

    public UniqueMenuItemCollectionHandler(MenuItemCollection menuItemCollection)
    {
        this.menuItemCollection = menuItemCollection;
        this.addedMenuItems = new HashSet<MenuItem>(menuItemCollection);
    }

    private bool IsMenuItemAdded(MenuItem menuItem)
    {
        return this.addedMenuItems.Contains(menuItem);
    }

    private void AddMenuItem(MenuItem menuItem)
    {
        if (!this.IsMenuItemAdded(menuItem))
        {
             this.menuItemCollection.Add(menuItem);
             this.addedMenuItems.Add(menuItem);
        }
    }
    private void RemoveMenuItem(MenuItem menuItem)
    {
        if (this.IsMenuItemAdded(menuItem))
        {
             this.menuItemCollection.Remove(menuItem);
             addedMenuItems.Remove(menuItem);
        }
    }
}

The most neat solution would be that you'd create your own derived class of MenuItemCollection. However, you can't assign this to the MenuItemCollection of your menu: it is read-only.

Another method would be that you create a derived class of ContextMenu where you make sure that menu items can only be added via your functions, but alas: the needed methods are not virtual, so you can't override them.

The only method that is left is that you create your own control, similar to a ContextMenu, but I think the amount of work needed for that never weighs up against the benefits of this special control.

Create a class that asserts that you have only unique menuItems. If you derive it from MenuItemCollection, you can't guarantee that people won't use one of the Add methods of the base class. S

class UniqueMenuItemCollection : MenuItemCollection
{
    public Dictionary(MenuItemId, MenuItem
}

You can assign this enum value to the Tag of the context

Harald Coppoolse
  • 28,834
  • 7
  • 67
  • 116