First of all please excuse my lousy English :(
I’m trying to copy the Outlook-SendTo-Context-Menu.
When you type in a EMail address, it will ShowUp and „Auto-Complete-Menu“ with an X to delete entries out of the list.
And there is my Problem, i can create a Conext Menu like:
foreach (string item in hist)
{
if (String.IsNullOrWhiteSpace(item)) continue;
MenuItem mI = new MenuItem();
Button mB = new Button();
mB.Content = "X";
mB.Click += new RoutedEventHandler(menuItemClick_Delete);
mI.Header = item;
mI.Tag = item;
mI.Click += new RoutedEventHandler(menuItemClick_SelectFolder);
//mI.Icon = mB;
mB.Tag = mI;
// mB.IsMouseOver +=
//submI.Header = "Löschen";
//submI.Tag = item;
///submI.Click += new RoutedEventHandler(menuItemClick_Delete);
cm.Items.Add(mI);
}
return cm;
I tryed to add a Icon/Image, but it looks ugly. Because the button is in-front of the text and not behind.
I will post you an Image of what i mean ->
Maybe there is already a Component for, or its not working like i thought.. i'm open for almost everything :)
Thanks for far!
Related
I am creating dynamically buttons in windows forms by using the code below. I want to have a context menu with different options pop up when a button is being right clicked. I made the context menu strp and it shows up but i cant figure out how to make the different options perform the functions i have written for them. Any idea how i can connect the items to their functions ?
void AddButton(Shape s){
Button b = new Button();
b.Text = s.name;
b.Width = sceneItemsList.Width-6;
b.TabStop = false;
b.FlatStyle = FlatStyle.Flat;
b.BackColor = Color.LightGray;
b.FlatAppearance.BorderColor = Color.Black;
ContextMenuStrip cm = new ContextMenuStrip();
cm.Items.Add("Deselect");
cm.Items.Add("Edit");
if (s is GroupShape)
{
cm.Items.Add("Ungroup");
}
cm.Items.Add("Delete");
b.ContextMenuStrip = cm;
}
Figured it out! This is my code if anyone else is struggling with this. Basically you make a loop that goes through all the opptions and adds a click eventhadler
cm.Items[0].Click += (sender, e) => {
Console.WriteLine("ok");
};
Premise:-
We have a list of key value pairs.
The Item count of this list will vary.
We have a form with a bunch of default buttons on it. (Edit - Built earlier in the designer, not at runtime.)
The buttons are named "button1, button2, ..."
We have more buttons than items in the list.
At runtime we want to transfer information from the list elements to the buttons and hide the unused buttons.
My question is how to address those buttons from withing a loop?
Using a for loop in VBA I could say this:-
Me.Controls("TB_Item" & Format(i, "00")).Visible = False
In C# I have this minimal example as a starting point (The form has 10 buttons):-
public UF_ButtonLoop()
{
InitializeComponent();
List<KeyValuePair<string, string>> MyItems = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("Apple", "Green Fruit"),
new KeyValuePair<string, string>("Orange", "Orange Fruit"),
new KeyValuePair<string, string>("Sprout", "Spawn of the Devil"),
new KeyValuePair<string, string>("Hershey Bar", "A bit like chocolate"),
new KeyValuePair<string, string>("Beefburger", "Man Food")
};
//Loop through the 10 buttons
for (int i = 1; i < 11; i++)
{
if (i <= MyItems.Count )
{
//Transfer Data from list to button
//Pseudo code
Control("Button" + i).Text = (MyItems.ElementAt(i).Key);
Control("Button" + i).Tag = (MyItems.ElementAt(i).Value);
}
else
{
//Hide the button as we've reached the end of the list so have no use for it.
//Pseudo code
Control("button" + 1).Hide();
}
// Note, VBA methos is:-
// Me.Controls("TB_Item" & Format(i, "00")).Visible = False
}
}
Control("Button" + i) is not correct syntax.
Can I do this in C#, if so how?
If not what is the correct way?
Also I'm new here so if I'm asking things in the wrong way please don't be shy in telling me so!
Many thanks,
Owen S.
Firstly thanks for the help, it's appreciated, especially the nudge towards doing it via other methods, or even different controls.
The answer to the question is probably split into two options:-
(Answer 1) - Do it properly by creating just what you need at runtime, rather than using the static designer and then hiding what was over-built.
(Answer 2) - Quick "bodge" to get the code in my initial question working. (My C# experience can be measured in hours so I have plenty to learn but also need to get code working today for work...)
So one bodge method that works is to put the buttons in their own list and then reference that. Like so:-
public UF_ButtonLoop()
{
InitializeComponent();
//TransferListToButtone_Rev1();
List<KeyValuePair<string, string>> MyItems = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("Apple", "Green Fruit"),
new KeyValuePair<string, string>("Orange", "Orange Fruit"),
new KeyValuePair<string, string>("Sprout", "Spawn of the Devil"),
new KeyValuePair<string, string>("Hershey Bar", "A bit like chocolate"),
new KeyValuePair<string, string>("Beefburger", "Man Food")
};
List<Control> ListOfButtons = new List<Control>
{
button1, button2, button3, button4, button5, button6, button7, button8, button9, button10
};
void A_Button_Click(object sender, System.EventArgs e)
{
Console.WriteLine((sender as Button).Text + " = " + (sender as Button).Tag);
}
//Loop through the 10 buttons
for (int i = 0; i < 10; i++)
{
if (i < MyItems.Count )
{
//Transfer Data from list to button
ListOfButtons.ElementAt(i).Text = (MyItems.ElementAt(i).Key);
ListOfButtons.ElementAt(i).Tag = (MyItems.ElementAt(i).Value);
//Set Click Event
ListOfButtons.ElementAt(i).Click += new EventHandler(A_Button_Click);
}
else
{
//Hide the button as we've reached the end of the list so have no use for it.
ListOfButtons.ElementAt(i).Hide();
}
}
}
Cheers all,
Owen S.
I would recommend to create those buttons when you read the list. Do not create the buttons statically in designer. You need to create a List of buttons in the main Form and then add the buttons programmatically.
List creation
List<Button> buttons = new List<Button>();
Then in some loop where you go thru your data list
Button MyButton = new Button();
Mybutton.Location = new Point(YourX, YourY);
Mybutton.Text = "AnyText";
Mybutton.AutoSize = false;
MyButton.Size = new Size(width, height);
Mybutton.BackColor = Color.LightBlue;
Mybutton.Padding = new Padding(6);
buttons.add(MyButton);
Ad1.
The best practice is to create your own "SpecialButton" class which is Inheritted from original Button class. Then you can add some special attributes to the button as is reference on some other element which should the SpecialButton control and etc...
I got a menu item, which when you press different toolstripmenu items show. But I want to add subtoolstripmenu items to a toolstripmenuitem. This is how I thought it would work:
ToolStripMenuItem[] items = new ToolStripMenuItem[10];
for (int i=0;i<10;i++)
{
items[i] = new ToolStripMenuItem();
items[i].Name = i;
items[i].Text = i;
items[i].Tag = i;
items[i].Click += new EventHandler(MenuItemClickHandler);
}
toolStripMenuItem1.DropDownItems[2].AddRange(items); //not possible
toolStripMenuItem1.DropDownItems.AddRange(items); // possible
Sadly it only works when I use toolStripMenuItem1.DropDownItems.AddRange(items); but not when I use toolStripMenuItem1.DropDownItems[2].AddRange(items);. Anyone any idea how to do this?
I dont want it to expand at the red cross, i want the green circle: http://imgur.com/a/mFWAz
LarsTech's comment is correct.
Replace the last 2 lines with:
ToolStripMenuItem subMenu = toolStripMenuItem1.DropDownItems[2] as ToolStripMenuItem;
subMenu.DropDownItems.AddRange(items);
I have a form which contains a dynamically added TableLayoutPanel, which contains some dynamically added Labels, TextBox, CheckBox. I am obtaining exactly the visualization I would like to have, but I am struggling to get the "tab key" to work for moving from one control to the other.
I have tried to add a:
control.TabIndex = tabIndex++;
control.TabStop = true;
But this doesn't seem to have any impact...
This is the (tested) stub code:
class MyForm : Form
{
public MyForm()
{
InitializeComponent();
string[] titles = {"first","second"};
var myLayout = new TableLayoutPanel();
myLayout.AutoSize = true;
int myTabIndex = 1; //Not really necessary
int rowNumber = 0;
foreach (var title in titles)
{
var label = new Label();
label.Text = title;
myLayout.Controls.Add(label, 0, rowNumber);
var control = new TextBox();
control.TabIndex = myTabIndex++; //Not really necessary
myLayout.Controls.Add(control, 1, rowNumber);
rowNumber++;
}
this.Controls.Add(myLayout);
}
}
This is the window I get, and I am not able to navigate from first to second field using the tab key.
Update:
Applying Visual Studio 2013 Update 5 did not help.
Something must have been corrupted in my project. The best I could do is to move on with a new clean Windows Form project, and everything now is working.
I am new to C# and WinForms. I have some objects with the right click (context menu) events. However, depending on the context (for example depending on whether the user is in the wizard screen or the main screen), I want to alter what the right click does. I googled a bit and found that I can use += and -= operators but I still could not achieve what I want to do. Given the code below, for example,
Any ideas ?
EDIT: I want the OnClickCard behave differently in different places.
Sammple Code:
public override ContextMenuStrip GetContextMenuStrip(GoView view)
{
if (Selectable)
{
ContextMenuStrip contextMenu = new ContextMenuStrip();
if (!Empty)
{
// this is just for example so not showing the implementation
contextMenu.Items.Add(new ToolStripMenuItem(
"Delete",
null,
new EventHandler(OnClickDelete)));
}
// Empty
else
{
ToolStripMenuItem addCard = new ToolStripMenuItem("Add");
foreach (..some data..)
{
ToolStripMenuItem card = new ToolStripMenuItem(
data,
null,
new EventHandler(OnClickCard));
addCard.DropDownItems.Add(card);
}
}
}
else
{
return null;
}
}
private void OnClickCard(object sender, EventArgs e)
{
ToolStripMenuItem cardItem = (ToolStripMenuItem)sender;
if (cardItem.Text.Contains("ABC"))
{
Common.Forms.FormMMUSettings f = new FormMMUSettings(cardItem.Text,ParentMagazine.NextSite);
f.Show();
}
SetCard(new MagazineCard(2, cardItem.Text));
}
Are you saying you want to change the contents of the context menu depending on the circumstances when it's clicked? If so, the easiest way is to create multiple context menus, and just use an event to set whichever context menu you want.
ContextMenu menu1 = new ContextMenu();
MenuItem menu1Item1 = new MenuItem();
menu1Item1.Header = "Menu 1 Item 1";
menu1Item1.Click += new RoutedEventHandler(menu1Item1Clicked);
menu1.Items.Add(mnu1Item1);
MenuItem menu1Item2 = new MenuItem();
menu1Item2.Header = "Menu 1 Item 2";
menu1Item2.Click += new RoutedEventHandler(menu1Item2Clicked);
menu1.Items.Add(menu1Item2);
ContextMenu menu2 = new ContextMenu();
MenuItem menu2Item1 = new MenuItem();
menu2Item1.Header = "Menu 2 Item 1";
menu2Item1.Click += new RoutedEventHandler(menu2Item1Clicked);
menu2.Items.Add(menu2Item1);
MenuItem menu2Item2 = new MenuItem();
menu2Item2.Header = "Menu 2 Item 2";
menu2Item2.Click += new RoutedEventHandler(menu2Item2Clicked);
menu2.Items.Add(menu2Item2);
public void menu1Item1Clicked(object sender, EventArgs e)
{
}
etc..
Now you can just set whichever menu you need using:
myForm.ContextMenu = menu1;
Hope this helps.
+= and -= should work just fine but I'd suggest you to use a kind of handlers repo where you'd switch which handler to use. This should work like a strategy pattern where different wizard steps would be different strategies.
It would be easier to help you if you'll show us some code and point us which code parts do not work properly.
You seem to suggest that you would like to attach different handlers depending on context:
if(that)
obj.event += HandleThat;
else
obj.event += HandleSomethingElse;
That should work, but you can also do it in one handler:
obj.event += HandleAll;
void HandleAll(object sender, EventArgs arg) {
if(that)
HandleThat();
else
HandleSomethingElse();
}
EDIT: ok, your edited question really meant something else.
First obvious problem is that you add OnClickDelete as a handler, and show the implementation of OnClickCard which will not be called in your example. If it is a typo, then you just need to implement the handler method as you need. What part exactly is not working?