Dynamically generate menustrip items - c#

I have a database row with a primary key index and strUsername and I'm using these to dynamically generate dropdown items in a menu strip. The code gives the dropdown item the username string as it's text value and creates an event handler. I want to pass the primary key integer to the click event method but the code I've got gives all the click event methods the database row.count value. Can anyone help please?
// Generate drop down items from database
daUsers.Fill(dtUsers);
// Update mnuFileNew drop down list
if (dtUsers.Rows.Count != 0)
{
mnuFileNew.DropDownItems.Clear();
foreach (dbAutoBloggerDataSet.dbTblUsersRow row in dtUsers.Rows)
{
ToolStripMenuItem newItem = new ToolStripMenuItem(row.strUsername);
newItem.Click += new EventHandler((sender, e) => mnuFileNewUser_Click(sender, e, row.nId));
mnuFileNew.DropDownItems.Add(newItem);
}
}
// Drop down item event handler
private void mnuFileNewUser_Click(object sender, EventArgs e, int nId)
{
frmLogin frmLogin = new frmLogin(nId);
DialogResult result = frmLogin.ShowDialog();
if (result == DialogResult.OK)
{
frmProfile frmProfile = new frmProfile(frmLogin.nId);
frmProfile.ShowDialog();
screenRefresh();
}
}

I think this sample code is useful
void AddMenuItem(string text, string action)
{
ToolStripMenuItem item = new ToolStripMenuItem();
item.Text = text;
item.Click += new EventHandler(item_Click);
item.Tag = action;
//first option, inserts at the top
//historyMenu.Items.Add(item);
//second option, should insert at the end
historyMenuItem.DropDownItems.Insert(historyMenuItem.DropDownItems.Count, item);
}
private void someHistoryMenuItem_Click(object sender, EventArgs e)
{
ToolStripMenuItem menuItem = sender as ToolStripMenuItem;
string args = menuItem.Tag.ToString();
YourSpecialAction(args);
}

Related

How can I make an image appear in Windows Forms C# when a specific value in ComboBox is selected?

I am trying to make a drop down list with several options ( educational majors ) and when the user selects a specific value ( educational major ) a study plan of that Major appears.
I already did the drop down list as follows:
InitializeComponent();
string i = "Information Technology";
string m = "Medical Lap";
comboBox1.Items.Add(i);
comboBox1.Items.Add(m);
comboBox1.DropDownStyle = ComboBoxStyle.DropDownList;
And now remains the process when a value is selected an image related to that value appears.
Based on your description, you want to show the correspond image when you select an item from combobox.
I suggest that you can use Dictionary to do it.
Here is a code example you can refer to.
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
foreach (var item in dic)
{
if(item.Key==comboBox1.SelectedItem.ToString())
{
pictureBox1.Image = item.Value;
}
}
}
Dictionary<string, Image> dic = new Dictionary<string, Image>();
private void Form1_Load(object sender, EventArgs e)
{
dic.Add("Information", Image.FromFile("D:\\1.jpg"));
dic.Add("Medical", Image.FromFile("D:\\2.jpg"));
dic.Add("Political", Image.FromFile("D:\\3.jpg"));
dic.Add("biological", Image.FromFile("D:\\4.jpg"));
foreach (var item in dic)
{
comboBox1.Items.Add(item.Key);
}
comboBox1.DropDownStyle = ComboBoxStyle.DropDownList;
pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
}
The result:
You will need to create an event handler that subscribes to the SelectedIndexChanged event of the combobox and inside of that event handler write the code that will display the proper image.
https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.combobox.selectedindexchanged?view=netcore-3.1
if you created the combobox using VS once you double click on it creates the event handler for you , and attach it to the control, however if you need to add that manually you will need to do that in the initialize function see below
public Form1()
{
InitializeComponent();
}
private void InitializeComponent()
{
this.comboBox1 = new System.Windows.Forms.ComboBox();
this.SuspendLayout();
//
// comboBox1
//
this.comboBox1.FormattingEnabled = true;
this.comboBox1.Location = new System.Drawing.Point(174, 68);
this.comboBox1.Name = "comboBox1";
this.comboBox1.Size = new System.Drawing.Size(121, 21);
this.comboBox1.TabIndex = 0;
this.comboBox1.SelectedIndexChanged += new
***System.EventHandler(this.comboBox1_SelectedIndexChanged);***
}
Properties of the Combobox to assign event handler
after that you need to insert the code that will define the source of the picture box
example
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
string picturelocation = "";
picturelocation =#"c:\images\" + comboBox1.Text + ".jpg" ;
pictureBox1.ImageLocation = picturelocation;
}
where the combobox1.text will be your file names

How to add a click action to ToolStripMenuItem.DropDown items that were created dynamically?

So I creating some items in favsToolStripMenuItem.DropDown (ToolStripMenuItem) based on a file:
using (StreamReader reader = new StreamReader("text.ini"))
{
while (true)
{
string line = reader.ReadLine();
if (line== null)
break;
favsToolStripMenuItem.DropDown.Items.Add(line);
}
}
But how can I add click event for them? I want a click event based on the item's name (text).
Stub out your click method:
private void DropDown_Click(object sender, EventArgs e) {
ToolStripItem tsi = sender as ToolStripItem;
if (tsi != null) {
MessageBox.Show(tsi.Text);
}
}
and then use the Add parameter that includes the Event Handler:
favsToolStripMenuItem.DropDown.Items.Add(line, null, DropDown_Click);
First you need to assign the event when creating each menu item.
using (StreamReader reader = new StreamReader("text.ini"))
{
while (true)
{
string line = reader.ReadLine();
if (line== null)
break;
ToolStripMenuItem menu = new ToolStripMenuItem(line);
menu.Click += new EventHandler(menu_Click);
favsToolStripMenuItem.DropDown.Items.Add(menu);
}
}
Now, each submenu item has its own event to trigger when clicked. This is how you select which event to trigger based on the name/text of the item,
void menu_Click(object sender, EventArgs e)
{
var menuItem = sender as MenuItem;
var menuText = menuItem.Text;
switch(menuText) {
case "MenuItem1":
// menu item1 clicked .. do something
break;
case "MenuItem2":
// menu item2 clicked .. do something
break;
. ...
}

Dynamically add item to DataGridView ComboBox Column by typing in the cell

I have a DataGridView that has a ComboBox column and I must update each ComboBox's possible values when its drop down shows. I also must make the ComboBoxes capable of having custom typed values. When a new value is typed, it should be added to the list of possible values. The problem is that I get infinitely many DataError event triggers (error message boxes), I know how to handle it by just changing a field in the DataGridViewDataErrorEventArgs object, but I know it is not the correct way to handle it:
private void DataGridView1_DataError(object sender, DataGridViewDataErrorEventArgs e)
{
e.Cancel = false;
}
If I do it in the incorrect way, after selecting a value from the drop down or typing a new value, the CellValueChanged is triggered but the closed ComboBox does not display the current value but an already existing value (the first in the list).
In the following code the Form subclass is Form2, the initial values are stored in the str field and the UpdatePossibleValues method is called to update the possible values in all the ComboBoxes inside the only column in the data grid view, a DataGridViewComboBoxColumn:
public Form2()
{
InitializeComponent();
dataGridView1.EditingControlShowing += DataGridView1_EditingControlShowing;
UpdatePossibleValues();
}
internal List<string> str = new List<string>()
{
"val1",
"val2"
};
private void DataGridView1_EditingControlShowing(object sender,
DataGridViewEditingControlShowingEventArgs e)
{
if (dataGridView1.CurrentCell == null ||
dataGridView1.CurrentCell.OwningColumn == null ||
dataGridView1.CurrentCell.OwningColumn.Name != "column1")
{
return;
}
var combo = e.Control as DataGridViewComboBoxEditingControl;
if (combo == null)
{
return;
}
var cb = combo as ComboBox;
UpdatePossibleValues(cb);
cb.DropDownStyle = ComboBoxStyle.DropDown; // this makes the ComboBoxes editable
cb.Validating += Cb_Validating;
}
private void Cb_Validating(object sender, System.ComponentModel.CancelEventArgs e)
{
var cbo = sender as ComboBox;
string t = cbo.Text;
var cell = (DataGridViewComboBoxCell)dataGridView1.CurrentCell;
// add the value to the list if it is not there
if (!string.IsNullOrEmpty(t) &&
!cbo.Items.Contains(t))
{
str.Add(t);
UpdatePossibleValues(cbo);
cell.Value = t;
e.Cancel = false;
}
}
private void UpdatePossibleValues(ComboBox cb = null)
{
if (cb == null)
{
var col = dataGridView1.Columns[0] as DataGridViewComboBoxColumn;
col.Items.Clear();
foreach (string s in str)
{
col.Items.Add(s);
}
}
else
{
cb.Items.Clear();
foreach (string s in str)
{
cb.Items.Add(s);
}
}
}
Screenshots:
To dynamically add item to DataGridViewComboBoxColumn:
Hanlde EditingControlShowing and get the DataGridViewComboBoxEditingControl
Set editing control DropDownStyle to DropDown
Handle Validating event of editing control and make sure you attach the event handler just once.
Check if the Text of the editing control doesn't exists in the items:
Add it to data source of the column
Then reset data source of the column by setting it to null and assigning data source again.
Notes:
If you have multiple combo box, make sure you use different data sources for combo boxes and update corresponding data source in validating event.
If you handle the events using anonymous method, make sure you have a correct assumption about captured variables. To make it simple, you can handle the event using a normal method.
Example
The following example shows a DataGridView having two DataGridViewComboBoxColumn which for the second one, you can add new values by typing in the combo box at run-time.
To run the example, create a Form and drop a DataGridView on a new Form and just copy and paste the following code in the form:
private List<String> comboSource1;
private List<String> comboSource2;
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
comboSource1 = new List<string> { "A", "B" };
comboSource2 = new List<string> { "1", "2" };
var dt = new DataTable();
dt.Columns.Add("C1");
dt.Columns.Add("C2");
dt.Rows.Add("A", "1");
dt.Rows.Add("B", "2");
var c1 = new DataGridViewComboBoxColumn();
c1.Name = "C1";
c1.DataPropertyName = "C1";
c1.DataSource = comboSource1;
var c2 = new DataGridViewComboBoxColumn();
c2.Name = "C2";
c2.DataPropertyName = "C2";
c2.DataSource = comboSource2;
dataGridView1.Columns.AddRange(c1, c2);
this.dataGridView1.DataSource = dt;
dataGridView1.EditingControlShowing += dataGridView1_EditingControlShowing;
dataGridView1.EditMode = DataGridViewEditMode.EditOnEnter;
}
private void dataGridView1_EditingControlShowing(object sender,
DataGridViewEditingControlShowingEventArgs e)
{
var dataGridView = sender as DataGridView;
if (dataGridView?.CurrentCell?.ColumnIndex != 1) return;
var comboBox = e.Control as DataGridViewComboBoxEditingControl;
if (comboBox == null) return;
comboBox.DropDownStyle = ComboBoxStyle.DropDown;
if (!true.Equals(comboBox.Tag))
{
comboBox.Tag = true;
comboBox.Validating += (obj, args) =>
{
var column = (DataGridViewComboBoxColumn)dataGridView.CurrentCell.OwningColumn;
var list = comboBox.DataSource as List<string>;
if (list == null) return;
var txt = comboBox.Text;
if (!list.Contains(txt))
{
list.Add(txt);
column.DataSource = null;
column.DataSource = list;
}
dataGridView.CurrentCell.Value = txt;
dataGridView.NotifyCurrentCellDirty(true);
};
}
}

MenuItem Click event handler not called

I´m building a ContextMenu on the fly, like this
readinstance = null;
ContextMenu cMenu = new ContextMenu();
for (int i = 0; i < instances.Length; i++) {
string text = String.Format("{0} - {1}", instances[i].Id, instances[i].FormName);
MenuItem item = new MenuItem(text, new EventHandler(cMenuitem_Click));
item.Tag = instances[i];
cMenu.MenuItems.Add(item);
}
cMenu.Show((Button)sender, new Point(0, 0));
cMenu.Dispose();
if (readinstance == null)
throw new Exception("Must select some instance");
and the handler is
void cMenuitem_Click(object sender, EventArgs e)
{
MenuItem item = (MenuItem)sender;
readinstance = (FormPrintingStorage)item.Tag;
}
The menu displays correctly, but when I click some of the options, the handler is not called, so readinstance remains null, and the exception throws. As a side note, when I click any of the options, the menu disappears.
I cannot see what is wrong with my code. Any help will be appreciated.
I´m answering my own question, because I tried more ways.
The first one was to replace the ContextMenu with a ListView and an "Ok" button, at no luck, because the wait loop needed a Thread.Sleep. No comments.
The solution was to implement a new dialog with an empty list view an the Ok button. Some of the relevant code follows. Note that only TreeViewItem/s are moved between the main form and the dialog.
ListViewItem _result = null;
public ListViewItem Result { get { return _result; } }
public List<ListViewItem> Source
{
set
{
listView1.Items.Clear();
foreach (ListViewItem item in value)
listView1.Items.Add(item);
listView1.View = View.List;
}
}
private void button1_Click(object sender, EventArgs e)
{
if (_result == null)
return;
DialogResult = DialogResult.OK;
Close();
}
private void listView1_SelectedIndexChanged(object sender, EventArgs e)
{
ListView list = (ListView)sender;
ListView.SelectedIndexCollection indices = list.SelectedIndices;
if (indices.Count == 0)
return;
_result = list.Items[indices[0]];
}
Getting the Result, the main form may do anything it wants with the Tag member. In fact, I´m using the same dialog for two different purposes in the same form.

How to loop through dropdown items in a toolstrip

I have a dropdown in my toolstrip (toolbar) i have attached a click event to each item in drop down as the dropdown has been populated dynamically, now i can casted the selected item in the dropdown and set its state to checked, to have a tick next to it, i wish to have a loop in another method to check which item has been checked. How do i loop through the items in the dropdown checking which item is checked?
foreach (DataSet1.xspLibraryByNameRow libName in data.xspLibraryByName)
{
var name = new LibraryItems(libName);
if (libName.xlib_Code != "NULL")
{
catDrpDwn.DropDown.Items.Add(name);
catDrpDwn.DropDown.Tag = name;
name.Click += new EventHandler(name_Click);
}
}
}
void mapArea_VE_MapReady(object sender, EventArgs e)
{
loadPoints();
}
void name_Click(object sender, EventArgs e)
{
var selected = (LibraryItems)sender;
selected.Checked = true;
loadPoints();
}
foreach (var items in catDrpDwn.DropDown.Items)
{
var it = (LibraryItems)items;
if (it.Checked == true)
{
}
}
Try this
var items=catDrpDwn.DropDown.Items.Cast<LibraryItems>().Where(d=>d.Checked).ToList();
here you will get all checked items and you can loop into it.

Categories

Resources