I have a ContextMenuStrip that I attach to several controls. It has the items { Add, Remove, Edit }. When a user right clicks on one of my listbox controls (which pops up this context menu) and selects 'Add', how can I derive the listbox control from the ToolStripMenuItem reference that is passed in?
private void OnAddEntry(object sender, EventArgs e)
{
// Example: ?????
ListBox lb = sender.Parent;
}
Mark, try this:
((ContextMenuStrip)(((ToolStripMenuItem)sender).Owner)).SourceControl
I'm guessing you can go up the chain of parents until you find the listbox.
You may be able to speed this up using the OwnerItem property to get straight to the toolstrip.
You could always set the item's Tag to the listbox and then just use it as require.
Related
I want to use TreeView in my software so when user clicks a node, the content of the Form will be changed. Example in this picture, but also I want to grab user input from all forms.
WinForms TreeView example
https://youtu.be/9BdYzMDxl9M?t=46
TreeView -> Node -> User Click -> Display Form_X in the GroupBox
I tried but I could not find related resources on this topic so I posted this question. Thank you for your help
Don't use forms as child controls. User controls exist specifically for that so use them. You add a user control to a project in the same way as you do a form, simply selecting a different menu option. You then design it and add code to it just as you would a form. Once you build your project, the user control will appear in the Toolbox and you can use it just like you would any other control. You then have a couple of options for how to handle switching controls via the TreeView.
If the number of controls is fairly small, you can add one of each to the GroupBox in the designer, so they all exist all the time. You would probably want to set the Dock property of each to Fill, so they all fill the parent GroupBox. In the Load event handler of the form, you can assign each user control instance to the Tag property of the corresponding TreeNode. When the user selects a node, you get the user control from its Tag property and call BringToFront on it, so the user will see it and it will hide all the other user controls, e.g.
private void Form1_Load(object sender, EventArgs e)
{
var nodes = treeView1.Nodes;
nodes[0].Tag = userControl1;
nodes[1].Tag = userControl2;
nodes[2].Tag = userControl3;
}
private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
{
var userControl = treeView1.SelectedNode.Tag as Control;
userControl?.BringToFront();
}
Because all the controls exist all the time, you can load all the data at the start and save all the changes at the end and not have to transfer any data when the selection changes.
If the number of controls is larger, you might want to show just one at a time. That becomes more complex because, when the selection changes, you have to make sure that any changes in the current user control are remembered, remove the existing control and then create and load the new control. Because the process is more complex, there are more options about exactly how to implement it. For that reason, I won't go into specifics here. If you want to go that way, you need to consider those options and how they relate to the specifics of your application and then decide how you want to implement the process. If you do that and encounter an issue along the way, that would be another question.
What have you tried? I am confident there are many ways to achieve what you describe. Since you mentioned a TabControl have you considered using a TabControl without the Tabs and manually switch to the proper tab page whenever the tree view node is clicked.
Something likeā¦
private void Form1_Load(object sender, EventArgs e) {
tabControl1.Appearance = TabAppearance.FlatButtons;
tabControl1.ItemSize = new Size(0, 1);
tabControl1.SizeMode = TabSizeMode.Fixed;
}
private void treeView1_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e) {
if (e.Node.Name == "TabPage1") {
tabControl1.SelectTab("TabPage1");
}
else {
tabControl1.SelectTab("TabPage2");
}
}
This is the part of my form that I am asking about
This is the tab index:
The problem that the tab goes from Farmer Audi Status to Yes, then to Ownder Bank Name instead of going to No
please notice that the yes and no already have 0.1.6.0 and 0.1.6.1 respectively.
could you help me please?
Notice
both radio buttons has TabStop property to True
From How to: Set the Tab Order on Windows Forms (MSDN):
A radio button group has a single tab stop at run time. The selected button (that is, the button with its Checked property set to true) has its TabStop property automatically set to true, while the other buttons have their TabStop property set to false.
In other words, what you're seeing is normal. Those "Yes/No" radio buttons are in the same group, and you can't tab between radio buttons in the same group. As you tab, you'll only focus on the currently selected one, then move to the next control on the form (in your case, a TextBox).
To work around this, you could place each radio button in its own container (such as a Panel), which means you'd have two "groups" each with one radio button. But then you lose the built-in functionality that automatically deselects one radio button when you select the other. Your user will be able to select both radio buttons, so you'd need to add some logic that disables the other. If you decide to try that, experiment with the radio buttons' CheckedChanged or Click / MouseClick events.
As Steve said, and as stated in the answer he linked to, the way it works out-of-the-box is expected behavior for Windows, so think twice before overriding it unless you have a good reason for doing so.
It worked for me!
first you have to create a method like this:
private void TabStopChanged(object sender, EventArgs e)
{
((RadioButton)sender).TabStop = true;
}
and then, put this in your Form_Load event:
private void Form_Load(object sender, EventArgs e)
{
foreach (var item in this.Controls)
{
if (item.GetType() == typeof(RadioButton))
((RadioButton)item).TabStopChanged += new System.EventHandler(TabStopChanged);
}
}
For radio buttons, you don't have to use Tab to navigate. Just use right and left keys to traverse radio buttons.
Check out this link to read more - https://www.csun.edu/universal-design-center/web-accessibility-criteria-tab-order
Sorry for the simple question and also sorry if there is an answer on the site and I couldn't find.
I want to use same textbox in every tab that I use on my form. How can I do that?
Add this to the TabControl's SelectedIndexChanged event handler.
private void tabControl1_SelectedIndexChanged(object sender, EventArgs e)
{
tabControl1.TabPages[tabControl1.SelectedIndex].Controls.Add(textBox1);
}
Adding a control to one tab page's Controls collection automatically removes it from the others.
Note: I have tested it by adding two lables on the form above the tab control and added these two lines to the method shown above:
label1.Text = tabControl1.TabPages[0].Controls.Count.ToString();
label2.Text = tabControl1.TabPages[1].Controls.Count.ToString();
Put the TextBox in the parent control of the TabControl. It can hover over all the rest. You might need to rework the focus traversal though.
im having 24 controls(pictureboxes) using the same strip menu, on the click event of any item in that strip menu i would want to know which control that used this strip menu item
for instance
private void getInfoToolStripMenuItem_Click(object sender, EventArgs e)
{
...
}
how to determine which control from the 24 controls that's using this menu
if it's not possible, is there any way around that to achieve the same purpose ? (to have all the controls sharing the same code without having 24 menu for the 24 controls with writing the code in all of them)
thanks and have a wonderful day
edit: for sake of clarification here is a rephrase of the problem
"a groupbox with 24 pictureboxes inside, all sharing same strip menu, i would want to determine which picturebox clicked the strip menu item so i can use that in the code to do something with the name of control (matching it with a keyvaluepair list)"
here is a picture
all i want to know which picturebox of those had clicked getinfo, that's it
After some replies, it's clear that you want to get the control clicking on which the ContextMenuStrip is popped up. Simply you can use the SourceControl property to get that control.
private void getInfoToolStripMenuItem_Click(object sender, EventArgs e) {
PictureBox pb = contextMenuStrip1.SourceControl as PictureBox;
}
The tricky part is that each item has a ContextMenu that I still want to open when it is right-clicked (I just don't want it selecting it).
In fact, if it makes things any easier, I don't want any automatic selection at all, so if there's some way I can disable it entirely that would be just fine.
I'm thinking of just switching to an ItemsControl actually, so long as I can get virtualization and scrolling to work with it.
If you don't want selection at all I would definitely go with ItemsControl not ListBox. Virtualization and scrolling both can be used with a plain ItemsControl as long as they are in the template.
On the other hand, if you need selection but just don't want the right click to select, the easiest way is probably to handle the PreviewRightMouseButtonDown event:
void ListBox_PreviewRightMouseButtonDown(object sender, MouseButtonEventArgs e)
{
e.Handled = true;
}
The reason this works is that ListBoxItem selection happens on mouse down but context menu opening happens on mouse up. So eliminating the mouse down event during the preview phase solves your problem.
However this does not work if you want mouse down to be handled elsewhere within your ListBox (such as in a control within an item). In this case the easiest way is probably to subclass ListBoxItem to ignore it:
public class ListBoxItemNoRightClickSelect : ListBoxItem
{
protected override void OnMouseRightButtonDown(MouseButtonEventArgs e)
{
}
}
You can either explicitly construct these ListBoxItems in your ItemsSource or you can also subclass ListBox to use your custom items automatically:
public class ListBoxNoRightClickSelect : ListBox
{
protected override DependencyObject GetContainerForItemOverride()
{
return new ListBoxItemNoRightClickSelect();
}
}
FYI, here are some solutions that won't work along with explanations why they won't work:
You can't just add a MouseRightButtonDown handler on each ListBoxItem because the registered class handler will get called before yours
You can't handle MouseRightButtonDown on ListBox because the event is directly routed to each control individually