Using string for control objects - c#

For my current project i made a MDIform with "menuStrip" and a couple of "ToolStripMenuItem".
a couple of buttons and a devexpress "NavbarControl"
The intention is that the user logs in with a userID
the application will get a datarow for a specific "Control"
in this row theirs a bool, if its true the Item must be visible, otherwise the item must be invisible.
the Datarow also contains the name of the item.
so i uses:
this.Controls[item].Visible = true;
item = string(name of item)
if i use this to hide the menustrip itself, it works
if i try it on the MenuStipItems, it gives a null reference exception.
how can i control the items INSIDE the MenuStip, only by name of the item???
Code:
DataTable dt = GetData();
foreach (DataRow row in dt.Rows)
{
string item = row["ItemNaam"].ToString();
foreach (string rol in Rollen)
{
DataRow dr = GetDataByItemNaam(item);
if (Convert.ToBoolean(dr[rol]) == true)
{
this.Controls[item].Visible = true; //Show Item
}
}
}

The MenuStrip control has it's own collection. So to reference the menu strip items, reference the items from the menustrip parent:
if (this.menuStrip1.Items.ContainsKey(item))
this.menuStrip1.Items[item].Visible = true;

I've solved the problem:
I created a foreach loop within a foreach loop where
each loop looks for the name of the item, and then for the name of the item in the previous item.
If the name matches the given name, it sets the visibility to true.
This is for 2 levels, I created an additional two extra foreach loops to go even deeper (inception) to 4 levels of items in the menu.
Perhaps its not the right/fastest way, but it works like it should.

Related

Dynamically add SubMenuItems to a SubMenu

I have a c# menu strip with top-level menu items (TLM items). I am dynamically adding items to one of the TLM items as follows, which works great.
DataRowCollection DRC = DataAccessClass.GetData("SELECT * FROM company ORDER BY CompanyName");
ToolStripMenuItem[] items = new ToolStripMenuItem[DRC.Count];
int itemCounter = 0;
foreach (DataRow dr in DRC)
{
string nm = dr["companyname"].ToString();
int id = Convert.ToInt16(dr["companyid"].ToString());
items[itemCounter] = new ToolStripMenuItem();
items[itemCounter].Name = string.Format("menuitem{0}", itemCounter);
items[itemCounter].Text = nm;
items[itemCounter].Click += new EventHandler(MenuItemClickHandler);
itemCounter++;
}
CompanyToolStripMenuItem.DropDownItems.AddRange(items);
Once this TLM has been populated, I want to dynamically add sub-menu items to each of the dynamic menu items created above. I am similarly creating an array of ToolStripMenuItems as above, and I am trying to add them to a menu item using this, shown here for the first menu item:
CompanyToolStripMenuItem.DropDownItems[0].DropDownItems.AddRange(submenuitems);
But it isn't working. Any ideas?
When I add CompanyToolStripMenuItem.DropDownItems[0] to a watch window, it is showing a "DropDownItems" property. When I try to type it in, the auto-complete drop-down isn't exposing the property as an option.
Try casting the selected DropDownItem item to a ToolStripMenuItem:
((ToolStripMenuItem)CompanyToolStripMenuItem.
DropDownItems[0]).DropDownItems.AddRange(submenuitems);

Selecting Multiple ListBox items from GridView column

I have a databound Listbox with Multiselect enabled. On page load, I feed the information from a GridView column and select all the options that match, using this code:
string[] separators = { "<br />" };
String Departments = Session["ProjDept"].ToString();
string[] splitDepartments = Departments.Split(separators, StringSplitOptions.RemoveEmptyEntries);
foreach (var dept in splitDepartments)
{
listDepartment.SelectedIndex = listDepartment.Items.IndexOf(listDepartment.Items.FindByText(dept));
}
However, I am running into a strange issue: when there is only one department in the GridView column, the option in the listbox gets properly selected, but when there's multiple departments only the LAST department gets selected.
I've ran System.Diagnostics.Debug.Print(dept) within my foreach to ensure that all the values are getting passed and they all appear in the STDOUT, but the listbox still won't cooperate.
Any ideas as to how I can fix this -- or alternatively, what other code could I use to achieve the same results?
Thank you!
The SelectedIndex property only allows one value at a time, so you're resetting it with each iteration. That's why only the last one is being selected. You need to access the "Selected" property from the ListItem itself.
Without trying it myself, it should look something like:
foreach (var dept in splitDepartments)
{
int index = listDepartment.Items.IndexOf(listDepartment.Items.FindByText(dept));
listDepartment.Items[index].Selected = true;
}
As long as you do have SelectionMode="Multiple" - that code should work.

Capturing whole ToolStripMenu tree with ToString

If I run the code in varying areas of my menu tree, I only get the one element, how would you firstly apply this logic to all sub components of this menu tree and secondly, illustrate the whole tree.
The code I have only shows 1 stage of each area applied
MessageBox.Show((ToolStripMenuItem).ToString());
So the above would only show File or Save or Open, rather than File Open or File Save.
Should I be using a foreach with my toolstripmenuitems?
Let's say I have MenuStrip with ToolStripMenuItem named fileToolStripMenuItem (with text File) which have subitems New and Open. Furthermore, Open has From file and Recent. To access all File's ToolStripMenuItems (it's children), you need recursive method, which goes through all levels (to access children, grandchildren...)
private IEnumerable<ToolStripMenuItem> GetChildToolStripItems(ToolStripMenuItem parent)
{
if (parent.HasDropDownItems)
{
foreach (ToolStripMenuItem child in parent.DropDownItems)
{
yield return child;
foreach (var nextLevel in GetChildToolStripItems(child))
{
yield return nextLevel;
}
}
}
}
This method takes first level menu item and returns IEnumerable<ToolStripMenuItem> sou you can then iterate through it (to get name, change some property etc).
Use it like this:
var list = GetChildToolStripItems(fileToolStripMenuItem);
In my example, that will return you the collection of subitems, like this: New, Open, From File, Recent.
You can easily go through collection and get item's text (to display in MessageBox, like this:
MessageBox.Show(string.Join(", ", list.Select(x=>x.Text).ToArray()))
or, if you prefer, like this:
foreach (ToolStripMenuItem menuItem in list)
{
MessageBox.Show(string.Format("item named: {0}, with text: {1}", menuItem.Name, menuItem.Text));
}
EDIT: after I saw comment that OP's idea is to get all items from MenuStrip, here's an example for that.
I wrote additional method that takes MenuStrip as parameter, iterates throught all ToolStripMenuItems and for each item calls GetChildToolStripItems method. Returns list of all top level items and all children and grand children...
private List<ToolStripMenuItem> GetAllMenuStripItems(MenuStrip menu)
{
List<ToolStripMenuItem> collection = new List<ToolStripMenuItem>();
foreach (ToolStripMenuItem item in menu.Items)
{
collection.Add(item);
collection.AddRange(GetChildToolStripItems(item));
}
return collection;
}
usage:
var allItems = GetAllMenuStripItems(menuStrip1)
Hope this helps.
In the end I used a logic around the following syntax, then building up the string at the end
ToolStripMenuItem ThisMenuItem = (ToolStripMenuItem)sender;
string WhatClicked = ThisMenuItem.ToString();
ToolStripMenuItem ThisMenuItemOwnerItem = (ToolStripMenuItem)(ThisMenuItem.GetCurrentParent() as ToolStripDropDown).OwnerItem;
Then you can obviously get deeper with
ToolStripMenuItem ThisOwnersOwnerItem = (ToolStripMenuItem)(ThisMenuItemOwnerItem.GetCurrentParent() as ToolStripDropDown).OwnerItem;
and so forth adding checks to avoid null exceptions.

Store elements from a ListView into a List

Since I haven't found anything that helped, I ask my question here:
I have a ListView where I select a whole row by click. Now I want to store these selected items into a List but don't know how this should work exactly.
List<String> itemSelected = new List<String>();
foreach (var selectedRow in listView1.SelectedItems)
{
itemSelected.Add(selectedRow);
}
That doesn't work because I need an index (selectedRow[?]) or something like that. How can I store the values of the first column when clicked the row?
EDIT: The problem is that the ListViewItems have the type "object"
The ListView gets populated this way:
using (SqlConnection connection = new SqlConnection(connectionQuery))
{
foreach (DataGridViewRow row in dataGridView1.SelectedRows)
{
col1 = row.Cells[col1.Text].Value.ToString();
col2 = row.Cells[col2.Text].Value.ToString();
col1Cells.Add(col1);
col2Cells.Add(col2);
}
}
You can do something like:
ListViewItem listViewItem = this.listView1.SelectedItems.Cast<ListViewItem>().FirstOrDefault();
if (listViewItem != null)
{
string firstColumn = listViewItem.Text;
string secondColumn = listViewItem.SubItems[0].Text;
// and so on with the SubItems
}
If you have more selected items and only need the values of the first columns you can use:
List<string> values = listView1.SelectedItems.Cast<ListViewItem>().Select(listViewItem => listViewItem.Text).ToList();
It's common to bind a ListView to the List of non-trivial types.
Then you can handle SelectedItemChanged or something like that. You receive the whole object (in type object) which you can cast to your custom type and retrieve any properties you want

Select the specific column of ListView and print it in a new messagebox in C#.net

I've just started to use ListView in C#.net.
I got to know how to add items and subitems. Going through the listview I wanted to fetch all the data from a whole column with multiple rows.
I want to know how to do this.
I found this code to list a specific selected data from a row:
ListView.SelectedIndexCollection sel = listView1.SelectedIndices;
if (sel.Count == 1)
{
ListViewItem selItem = listView1.Items[sel[0]];
MessageBox.Show(selItem.SubItems[2].Text);
}
That was helpful but i want to list all the items in a row, may be i want to add all the column items in array?
private string[] GetListViewItemColumns(ListViewItem item) {
var columns = new string[item.SubItems.Count];
for (int column = 0; column < columns.Length; column++) {
columns[column] = item.SubItems[column].Text;
}
return columns;
}
I would recommend some caution against doing this. A ListView is really meant to display information, it is not a great collection class. Getting the data out of it is slow and crummy, it can only store strings. Keep the data in your program in its original form, maybe a List<Foo>. Now it is simple and fast.
foreach (ListViewItem item in listView1.Items) {
// Do something with item
}
you could do this by
foreach(ListViewItem item in listView1.Items)
{
foreach(var subtem in item.SubItems)
{
// Do what ever you want to do with the items.
}
}

Categories

Resources