How to retrieve the name of a control created programmatically - c#

in an app where it is possible to create a serie of buttons programmatically, how can I retrieve the name of one of these buttons once I click its context menu?
This is the piece of code:
private void addButton_Click(object sender, System.EventArgs e)
{
int y = (buttonIndex * 80) + 5;
btn.Name = "btn" + buttonIndex.ToString();
btn.Content = "button " + buttonIndex.ToString();
btn.Width = 440;
btn.Height = 100;
Thickness margin = new Thickness(0, y, 0, 0);
btn.Margin = margin;
// .. all other properties..
pivot1Grid.Children.Add(btn);
buttonIndex++;
AddContextMenuItems(btn);
}
private void AddContextMenuWithMenuItems(Button btn)
{
ContextMenu contextMenu = new ContextMenu();
MenuItem menuItem1 = new MenuItem() { Header = "Edit", Tag = "Edit" };
MenuItem menuItem2 = new MenuItem() { Header = "Remove", Tag = "Remove" };
menuItem1.Click += new RoutedEventHandler(menuItem1_Click);
menuItem2.Click += new RoutedEventHandler(menuItem2_Click);
contextMenu.Items.Add(menuItem1);
contextMenu.Items.Add(menuItem2);
ContextMenuService.SetContextMenu(btn, contextMenu);
}
Now in the click event I should be able to get the name of the button clicked (it works in case the context menu is created directly in XAML):
void menuItem1_Click(object sender, RoutedEventArgs e)
{
string btnName = ((sender as MenuItem).Parent as ContextMenu).Name;
..
}
but it gives always an empty string.
Could you please tell me where is the mistake?
Thanks

In your code, you're casting sender.Parent to ContextMenu. So you know you are manipulating the ContextMenu object. Then why are you expecting to magically get the name of the button by querying the name of the context menu?
The easiest way in your case is to store your information in the Tag property of the context menu:
private void AddContextMenuWithMenuItems(Button btn)
{
ContextMenu contextMenu = new ContextMenu();
MenuItem menuItem1 = new MenuItem() { Header = "Edit", Tag = "Edit" };
MenuItem menuItem2 = new MenuItem() { Header = "Remove", Tag = "Remove" };
menuItem1.Click += new RoutedEventHandler(menuItem1_Click);
menuItem2.Click += new RoutedEventHandler(menuItem2_Click);
contextMenu.Items.Add(menuItem1);
contextMenu.Items.Add(menuItem2);
// Store the name of the button in the Tag property of the context menu
contextMenu.Tag = btn.Name;
ContextMenuService.SetContextMenu(btn, contextMenu);
}
Then, in the event handler, you just have to retrieve the value you've set before:
void menuItem1_Click(object sender, RoutedEventArgs e)
{
var contextMenu = (ContextMenu)((MenuItem)sender).Parent;
string btnName = (string)contextMenu.Tag;
..
}

Related

Get object/item on button click (dynamically created button) - stack panel

I am looping my customers, and for each customer I need to create one button in case
I would like to delete that specific customer.
So here is my code:
foreach (var item in customersList)
{
Button btn = new Button();
btn.Content = "Customer": + " " + item.Value;
btn.Height = 40;
btn.Click += btn_Click;
TextBox cust = new TextBox();
cust.Height = 40;
cust.Text = item.Value;
stackCustomers.Children.Add(cust);
stackCustomers.Children.Add(btn);
}
How could I attach event Click on my button so when I click on It I get customer?
void btn_Click(object sender, RoutedEventArgs e)
{
//I tried this but it is not working, unfortunatelly...
Customer cust = (Customer)sender;
}
The easy way: attach customer to the Button.Tag property
Button btn = new Button();
btn.Tag = item; // .Value maybe?
// ...
void btn_Click(object sender, RoutedEventArgs e)
{
var button = sender as Button;
Customer cust = (Customer)button.Tag;
}
What might be better: Create a visual representation of each customer item, where the button is contained. Use Button.Command and Button.CommandParameter={Binding PathToCustomer} instead of Button.Click.

How to get selected index of toolstripbutton in c#

I have a toolstrip control on a form and i programatically add buttons to the toolstrip control using the below code
toolStrip1.Visible = true;
ToolStripItem t = new ToolStripButton();
t.Text = client.EndPoint.ToString();
t.TextImageRelation = TextImageRelation.ImageAboveText;
t.BackgroundImage = Image.FromFile("" + Application.StartupPath + "ps1_new.PNG");
t.AutoSize = false;
t.Height = 67;
t.Width = 70;
t.BackgroundImageLayout = ImageLayout.Stretch;
t.TextAlign = ContentAlignment.BottomCenter;
toolStrip1.Items.Add(t);
Now i m trying to get the index of the toolstrip button when i click on it
note i can get the text of the clicked toolstripbutton using
e.ClickedItem.Text;
There isn't an index property on the toolstripitem click but you could do something like this
private void ToolStrip1_ItemClicked(object sender, EventArgs e)
{
MessageBox.Show(e.ClickedItem.Tag)
}
Where the Tag property is something you set as the index.

WPF / C# - Adding functionality to a button dynamically created inside a listbox

I have a button that adds this StackPanel to the listbox everytime it's clicked. In it is a button. I'm trying to figure out how to add code to this button that it's adding. Ideally I want the button to be a delete button, so it would delete that element (itself) in the list. I'm just trying to figure out how to add functionality to the button I'm dynamically creating. hope that makes sense
thanks for any help!
private void Button_Click_1(object sender, RoutedEventArgs e)
{
StackPanel stackPanel = new StackPanel();
stackPanel.Orientation = System.Windows.Controls.Orientation.Horizontal;
CheckBox checkBox = new CheckBox();
checkBox.IsChecked = true;
TextBox textBox = new TextBox();
textBox.Width = 100;
textBox.Text = textBox1.Text;
Button button = new Button(); //HOW DO I ADD CODE TO THIS BUTTON?
stackPanel.Children.Add(checkBox);
stackPanel.Children.Add(textBox);
stackPanel.Children.Add(button); //HOW DO I ADD CODE TO THIS BUTTON?
listBox1.Items.Add(stackPanel);
}
You can programatically add a click handler to the button like this:
Button button = new Button(); //HOW DO I ADD CODE TO THIS BUTTON?
button.Click += btn_Click;
stackPanel.Children.Add(checkBox);
stackPanel.Children.Add(textBox);
stackPanel.Children.Add(button); //HOW DO I ADD CODE TO THIS BUTTON?
and then you need the click event handler
void btn_Click(object sender, System.Windows.RoutedEventArgs e)
{
// your code to execute when the button is clicked.
stackPanel.Items.Remove(button);
}
Try This.
Add Stackpanel that have textblock and Button
private void OnSaveClick(object sender, RoutedEventArgs e)
{
StackPanel stp = new StackPanel();
stp.Orientation = Orientation.Horizontal;
stp.Children.Add(new TextBlock()
{
Text = string.Format("Item {0}", lstitems.Items.Count),
HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch
});
Button btn = new Button();
btn.Content = string.Format("Delete Item {0}", lstitems.Items.Count);
btn.Height = 25;
btn.Width = 100;
btn.HorizontalAlignment = System.Windows.HorizontalAlignment.Right;
btn.Click += btnDeleteClick;
stp.Children.Add(btn);
lstitems.Items.Add(stp);
}
Delete Button Click handler
void btnDeleteClick(object sender, RoutedEventArgs e)
{
Button btn = (Button)sender;
if (btn != null)
{
var st = FindParent<StackPanel> (btn); //stackpanel as we have added item as stackpanel.
if (st != null)
lstitems.Items.Remove(st);
}
}
To Find the Type to Object in the Visual Tree.
public T FindParent<T>(DependencyObject dependencyObject) where T : DependencyObject
{
var parent = VisualTreeHelper.GetParent(dependencyObject);
if (parent == null) return null;
var parentT = parent as T;
return parentT ?? FindParent<T>(parent);
}
That is the simplest setup. Ideally you want more error handling etc.
Button button = new Button();
button.Click += (s, args) => { listBox1.Items.Remove(stackPanel); };

Opening a ContextMenu from a ToolStripMenuItem

I am trying to mimic the behavior of, for example, Windows Explorer and how the Favorites items can launch a context menu.
I currently am using:
contextMenu.Show((sender as ToolStripMenuItem).GetCurrentParent().PointToScreen(e.Location));
This occurs in the MouseDown event of the ToolStripMenuItem. The problem is that the menu closes immediately after right-click, and I don't know any way to suspend it while the context menu is open.
I've tried deriving from ToolStripMenuItem and overriding the MouseDown/MouseUp but I can't figure out how to keep it open on click.
Is there a good way of doing this?
This is what I've had luck with, it's a bit more direct:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
void MenuItemContext(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left) return;
ToolStripMenuItem mID = (ToolStripMenuItem)sender;
ContextMenu tsmiContext = new ContextMenu();
MenuItem Item1 = new MenuItem();
MenuItem Item2 = new MenuItem();
Item1.Text = "Item1";
Item2.Text = "Item2";
tsmiContext.MenuItems.Add(Item1);
tsmiContext.MenuItems.Add(Item2);
Item1.Click += new EventHandler(Item1_Click);
Item2.Click += new EventHandler(Item2_Click);
hndPass = mID.Text;
tsmiContext.Show(menuStrip1, menuStrip1.PointToClient(new Point(Cursor.Position.X, Cursor.Position.Y)));
}
private String hndPass;
void Item1_Click(object sender, EventArgs e)
{
MenuItem mID = (MenuItem)sender;
MessageBox.Show("You clicked " + mID.Text + " in the context menu of " + hndPass);
}
void Item2_Click(object sender, EventArgs e)
{
MenuItem mID = (MenuItem)sender;
MessageBox.Show("You clicked " + mID.Text + " in the context menu of " + hndPass); ;
}
}
One way that you could accomplish this is by using the ToolStripDropDown control to host a ListBox inside of the ToolStripDropDown.
This may require some tweaking regarding the AutoClose behavior, but it should get you started:
First in your main form, add the following line to your ToolStripDropDropDown item
toolStripDropDownButton1.DropDown = new CustomListDropDown();
Then create a custom drop down class as follows:
public class CustomListDropDown : ToolStripDropDown
{
private ContextMenuStrip contextMenuStrip1;
private ToolStripMenuItem toolStripMenuItem1;
private ToolStripMenuItem toolStripMenuItem2;
private ToolStripMenuItem toolStripMenuItem3;
private System.ComponentModel.IContainer components;
public ListBox ListBox { get; private set; }
public CustomListDropDown()
{
InitializeComponent();
this.ListBox = new ListBox() { Width = 200, Height = 600 };
this.Items.Add(new ToolStripControlHost(this.ListBox));
this.ListBox.ContextMenuStrip = contextMenuStrip1;
this.ListBox.MouseDown += new MouseEventHandler(ListBox_MouseDown);
contextMenuStrip1.Closing += new ToolStripDropDownClosingEventHandler(contextMenuStrip1_Closing);
//add sample items
this.ListBox.Items.Add("Item1");
this.ListBox.Items.Add("Item2");
this.ListBox.Items.Add("Item3");
this.ListBox.Items.Add("Item4");
}
void contextMenuStrip1_Closing(object sender, ToolStripDropDownClosingEventArgs e)
{
this.Close();
this.AutoClose = true;
}
void ListBox_MouseDown(object sender, MouseEventArgs e)
{
this.AutoClose = false;
this.ListBox.SelectedIndex = this.ListBox.IndexFromPoint(e.Location);
}
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components);
this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem2 = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem3 = new System.Windows.Forms.ToolStripMenuItem();
this.contextMenuStrip1.SuspendLayout();
this.SuspendLayout();
//
// contextMenuStrip1
//
this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.toolStripMenuItem1,
this.toolStripMenuItem2,
this.toolStripMenuItem3});
this.contextMenuStrip1.Name = "contextMenuStrip1";
//
// contextMenuStrip1.ContextMenuStrip
//
this.contextMenuStrip1.Size = new System.Drawing.Size(181, 48);
//
// toolStripMenuItem1
//
this.toolStripMenuItem1.Name = "toolStripMenuItem1";
this.toolStripMenuItem1.Size = new System.Drawing.Size(180, 22);
this.toolStripMenuItem1.Text = "toolStripMenuItem1";
//
// toolStripMenuItem2
//
this.toolStripMenuItem2.Name = "toolStripMenuItem2";
this.toolStripMenuItem2.Size = new System.Drawing.Size(180, 22);
this.toolStripMenuItem2.Text = "toolStripMenuItem2";
//
// toolStripMenuItem3
//
this.toolStripMenuItem3.Name = "toolStripMenuItem3";
this.toolStripMenuItem3.Size = new System.Drawing.Size(180, 22);
this.toolStripMenuItem3.Text = "toolStripMenuItem3";
//
// CustomListDropDown
//
this.Size = new System.Drawing.Size(2, 4);
this.contextMenuStrip1.ResumeLayout(false);
this.ResumeLayout(false);
}
}
In my tests this worked reasonably well. Let me know how it goes.
As ContextMenuStrip is derived from ToolStripDropDown, you could do this:
private ContextMenuStrip CopyToContextMenu(ToolStripMenuItem mnuItemSource)
{
var mnuContextDestination = new ContextMenuStrip();
//Move itens from ToolStripMenuItem to ContextMenuStrip
while (mnuItemSource.DropDown.Items.Count > 0)
{
mnuContextDestination.Items.Add(mnuItemSource.DropDown.Items[0]);
}
//Put ContextMenuStrip in ToolStripMenuItem using DropDown property
mnuItemSource.DropDown = mnuContextDestination;
return mnuContextDestination;
}

Right click on a menu item and show options

I have menu ServerList, I am adding the menuItems dynamically using C# code. It reads the servers list from file and populate the menu items. I have added the right click options for each server. Edit & Delete.
All this is working fine. the problem is how do I read actual server name when Edit/Detele is clicked.
Here is the code
public MainWindow()
{
InitializeComponent();
LoadMenuItems();
}
//Currently static values, but reads from file. later
private void LoadMenuItems()
{
MenuItem item2 = new MenuItem();
item2.Header = "Server1";
AddContextMenu(item2);
MenuItem item3 = new MenuItem();
item3.Header = "Server2";
AddContextMenu(item3);
ActualMenu.Items.Add(item2);
ActualMenu.Items.Add(item3);
}
private void AddContextMenu(MenuItem item)
{
MenuItem item1 = new MenuItem();
item1.Header = "Edit";
item1.Click += item_Click;
MenuItem item2 = new MenuItem();
item2.Header = "Detlete";
item2.Click += item_Click;
ContextMenu menu = new ContextMenu();
menu.Items.Add(item1);
menu.Items.Add(item2);
item.ContextMenu = menu;
}
void item_Click(object sender, RoutedEventArgs e)
{
MenuItem item = sender as MenuItem;
string header = item.Header.ToString();
}
For this use PlacementTarget.
private void AddContextMenu(MenuItem item)
{
MenuItem item1 = new MenuItem();
....
ContextMenu menu = new ContextMenu();
....
menu.PlacementTarget = item; /// 'Connects' context menu to source menu item.
item.ContextMenu = menu;
}
void item_Click(object sender, RoutedEventArgs e)
{
MenuItem item = sender as MenuItem;
string header
= ((MenuItem)((ContextMenu)((MenuItem)sender).Parent).PlacementTarget).Header;
}
Cheers.
By default, the Header of a MenuItem uses a TextBlock to display content. So, in this case you need to convert the Header to a TextBox, then look at the Text property.
For example,
void item_Click(object sender, RoutedEventArgs e){
string servername = ((sender as MenuItem).Header as TextBlock).Text;
}

Categories

Resources