How to add custom control at Run time in c# - c#

i have one list box which has button, Textbox, Label. During runtime i will drag and drop the item from the list box, according to the selection the dynamic control will be created. (For example, If i select and drag Button from list box and drop it on the Windows Form, the button will be created). As same as i have created a CustomControl for Button. how can i add it in my list box at runtime? i mean while i drag and drop the button from the listbox the custom button should be generated. How to Do it?

Did You try this ?
var list = new ListBox();
list.Controls.Add(new Button());
If You need to dynamically create a class at runtime - take a look at this SF article How to dynamically create a class in C#?

For drag drop, you will need to set up 3 events:
A mouse down event on the list box to trigger the dragging:
private void listBox1_MouseDown(object sender, MouseEventArgs e)
{
listBox1.DoDragDrop(listBox1.SelectedItem, DragDropEffects.Copy);
}
A drag enter event on your form (or panel in this example):
private void panel1_DragEnter(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.Text))
{
e.Effect = DragDropEffects.Copy;
}
}
And finally the drop event on the form/panel:
private void panel1_DragDrop(object sender, DragEventArgs e)
{
Control newControl = null;
// you would really use a better design pattern to do this, but
// for demo purposes I'm using a switch statement
string selectedItem = e.Data.GetData(DataFormats.Text) as string;
switch (selectedItem)
{
case "My Custom Control":
newControl = new CustomControl();
newControl.Location = panel1.PointToClient(new Point(e.X, e.Y));
newControl.Size = new System.Drawing.Size(75, 23);
break;
}
if (newControl != null) panel1.Controls.Add(newControl);
}
For this to work you must set "AllowDrop" to true on the target form/panel.
Use #Marty's answer to add the custom control to the listbox. Override the ToString() for a better description. There are so many ways of doing it. The important part is deciding what data type the list items will be and making sure that the correct type name is used in the e.Data.GetDataPresent method. e.Data.GetFormats() can help determine what name to use.

Related

Getting a control name/Displaying tooltip text

I am developing a form with multiple options that simulates a signup form, and I want to display some tips and descriptions in a RichTextBox located by the options when the user's mouse hover by it's GroupBoxes.
Since I am fairly new to programming, I don't know if getting all the controls names one by one is the optimal, so I want to grab the controls' names inside of the tabControl control that I am using to organize everything.
private void TabControl1_MouseHover(object sender, EventArgs e)
{
foreach(Control c in this.Controls)
{
string name = c.Name;
TooltipText(name);
}
}
And I also have a method where I will write the text that will be displayed in the RichTextBox.
private string TooltipText(string name)
{
if(name == "Name:")
{
return "blabla";
}
else
{
return "none";
}
}
I've tried a generic method to show a message box if the control was detected and, as I suspected, nothing showed up:
private void TooltipText(string name)
{
if(name == "LBL_Name")
{
MessageBox.Show("hey");
return;
}
}
How can I properly detect the Groupboxes or other types of Controls inside of the TabControl control, and also display the text in the box beside it?
You don't have to create your own Tool Tips. The .net WinForms provides a ToolTip class. https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.tooltip?view=netframework-4.8
I added 2 radio buttons to a group box in design view.
Try it and see.
private void Form1_Load(object sender, EventArgs e)
{
ToolTip tip = new ToolTip();
tip.AutoPopDelay = 5000;
tip.InitialDelay = 1000;
tip.ReshowDelay = 500;
tip.SetToolTip(radioButton1, "Choose to Add Onions");
tip.SetToolTip(radioButton2, "Choose to Add Pickles");
}

Event that would listen to any label click in form

Well, I'm making a chess game that's based on labels. I need to listen for label click, so when user clicks on an label, I get the name of label he clicked. I know I can do it for each label, but is there an universal event that would help me do the same thing for all of them in one event / loop?
Suppose you have taken 64 labels.
In windows form, on click event of Label1 you will write following code:
private void Label1_Click(object sender, EventArgs e)
{
var label = sender as Label;
MessageBox.Show(label.Name);
}
For remaining 63 Lables, In Design view, select all 63 lables by using Ctrl key --> Go to Property window --> Under Event option select Click option --> From dropdownlist select 'Label1_Click' option.
Just finish & run the application.
You can use a Panel
structure to group your labels and then call the desired event on that Panel, so it will trigger whenever you click one of it's elements.
Another solution would be to identify your label with the coordinates of the mouse click (the amount of code that requires depends how you placed them of course).
Like mentioned in the comments you can assign one event to all...
List<Label> lbls = this.Controls.OfType<Label>().ToList();
foreach (var lbl in lbls)
{
lbl.Click += lbl_Click;
}
void lbl_Click(object sender, EventArgs e)
{
Label lbl = sender as Label;
MessageBox.Show(lbl.Name);
}
You can assign these methods to every label you need to manage in the VS form designer (you go to events of controls, at the click line and select the method in the list instead of double click on it):
private void Label_Click(object sender, EventArgs e)
{
var nameLabel = ( sender as Label )?.Name ?? "Error";
// ...
}
private void Label_Enter(object sender, EventArgs e)
{
( sender as Label ).Cursor = Cursors.Hand;
}
private void Label_Leave(object sender, EventArgs e)
{
( sender as Label ).Cursor = Cursors.Default;
}
Cursor change added for convenience if you want.
If you want to dynamically assign events, you can use the #caner answer, and you can group all in a panel to parse Panel.Controls and assign event.
You can create a custom label class that inherits from Label. You can then subscribe to the Click event of the base class and do your thing.
public class MyLabel : Label
{
public MyLabel()
: base()
{
Click += ProcessClickEvent;
}
private void ProcessClickEvent(object sender, System.EventArgs e)
{
// Do what you want to do
}
}

get textbox that is in the selected tab

I have a tabcontrol with numerous tabs that all contain a textbox. How can I select the textbox that is in the currently selected tab?
I have this which captures the tabchanged event and tells me which tab is selected, but I cannot figure out how to find the textbox that is in the tab and do
textbox.Select(0, 0);
to select certain text in this textbox...
private void onTabChange(Object sender, TabControlEventArgs e)
{
}
This really sounds like a design mistake. High odds that this TextBox should not be on a tab page at all. If you want to have one text box to be present on every tab page then that's possible, Winforms makes it easy to move controls:
private void tabControl1_SelectedIndexChanged(object sender, EventArgs e) {
textBox1.Parent = tabControl1.SelectedTab;
}
If you really meant for any text box to be picked, like the first one in the tab order then:
private void tabControl1_SelectedIndexChanged(object sender, EventArgs e) {
var box = tabControl1.SelectedTab.Controls.OfType<TextBox>().Reverse().FirstOrDefault();
if (box != null) {
// etc...
}
}
Use This:
Tab TabView = (Tab)sender;
TextView txt_Tab = (TextView)TabView.FindControl("TextBoxName");
Try this:
TextBox myTB = tabControl2.SelectedTab.Controls[0] as TextBox;
myTB.Select(0, 0);
I think the following links can provide you some hints about your problem
How to access controls that are inside a TabControl tab?
and
How to get control(s) from TabPage in C#?

C# Drag and Drop From listBox

I'm trying to build a simple interface that allows users to drop files into a listBox to add them to a process, and to drag them out to remove them. Everything is working fine, but I'd like to add one feature to make it just a tad more sophisticated.
Right now, I have the removal of the item tied to the DragLeave event, which means that as soon as the mouse leaves the box, the item is removed. But I'd like for users to be able to change their minds. In other words, if they realize they're dragging the wrong file out, I'd like them to be able to move the mouse back into the listBox and release the mouse to cancel the action. I'm thinking that means I need to be able to capture the MouseUp event instead of the DragLeave event. But that hasn't been successful so far.
Below is the code I'm currently using for removing files dragged out. How can I modify to keep the files from being removed form the list until the user lets the mouse button go?
private void listBox1_MouseDown(object sender, MouseEventArgs e)
{
if (listBox1.Items.Count == 0)
{
return;
}
int index = listBox1.IndexFromPoint(e.X, e.Y);
string s = listBox1.Items[index].ToString();
DragDropEffects dde1 = DoDragDrop(s, DragDropEffects.All);
}
private void listBox1_DragLeave(object sender, EventArgs e)
{
ListBox lb = sender as ListBox;
lb.Items.Remove(lb.SelectedItem);
}
Edit 2013/05/16
The comments and answers so far have been useful, but I realize my question isn't clear enough. In this case, I'm displaying a dialog separate from the parent form that is basically as big as the listBox. When someone drags a file out of the list, they're dragging it off the form completely. Have I backed myself into a corner by doing this? I recognize I'm making it harder than it has to be, but I'd still like to see how it would work if it's possible.
Here's a fairly quick hack approach to gaining the functionality you want:
public object lb_item = null;
private void listBox1_DragLeave(object sender, EventArgs e)
{
ListBox lb = sender as ListBox;
lb_item = lb.SelectedItem;
lb.Items.Remove(lb.SelectedItem);
}
private void listBox1_DragEnter(object sender, DragEventArgs e)
{
if (lb_item != null)
{
listBox1.Items.Add(lb_item);
lb_item = null;
}
}
private void listBox1_MouseDown(object sender, MouseEventArgs e)
{
lb_item = null;
if (listBox1.Items.Count == 0)
{
return;
}
int index = listBox1.IndexFromPoint(e.X, e.Y);
string s = listBox1.Items[index].ToString();
DragDropEffects dde1 = DoDragDrop(s, DragDropEffects.All);
}
private void Form1_DragDrop(object sender, DragEventArgs e)
{
lb_item = null;
}
Every time the user drags an item out of the box, it's saved temporarily until the user drops it somewhere else or mouses down on a new item in the list.
Note the important part of this is detecting when and where the user let's go of that mouse, which is the rationale behind handling the DragDrop event of Form1, the parent of listBox1.
Depending on the sophistication and density of the rest of your layout, where you handle DragDrop could be much different for you. This is why it's kind of "hacky", but it's also quite simple. It shouldn't matter, though, where or how many times you null lb_item since it pertains only to that specific ListBox.
I suppose another way to do it would be to track the user's mouse states and act accordingly, which may be more appropriate for you if it's inconceivable to handle a lot of DragDrop stuff.
EDIT: If you wanted to be REAL thorough, you could enumerate through every control of the base form using foreach and programmatically append a handler for the DragDrop event to that control, then remove it when done... but that may be getting a little nutty. I'm sure someone has a better approach.

Share an event handler across multiple controls

In my Windows forms application written in C# I have a bunch of buttons. When the user's mouse hovers over a button, I want the button's border to change.
Currently I have multiple instances of the following (a copy for each button):
private void btnStopServer_MouseEnter(object sender, EventArgs e)
{
oldColor = btnStopServer.FlatAppearance.BorderColor;
btnStopServer.FlatAppearance.BorderColor = mouseOverColor;
}
private void btnStopServer_MouseLeave(object sender, EventArgs e)
{
btnStopServer.FlatAppearance.BorderColor = oldColor;
}
Since I have a lot of buttons, the code to change the color of the button's border takes up a lot of space.
Is there any simpler way that I could do this?
You should wire-up a single MouseEnter and MouseLeave to each control that needs this functionality (rather than writing a new version of each method for each control). Assuming you're using Visual Studio, this can be done by changing the target method name for the event, in each Button's property pane. If you write the following code first, then this method will appear in the property's MouseEnter and MouseLeave events' drop-down lists.
The code would then need to check which button from which the event was fired, as follows:
private void btnWithHoverBorder_MouseEnter(object sender, EventArgs e)
{
Button eventButton = (Button) sender;
oldColor = eventButton.FlatAppearance.BorderColor;
eventButton.FlatAppearance.BorderColor = mouseOverColor;
}
private void btnWithHoverBorder_MouseLeave(object sender, EventArgs e)
{
Button eventButton = (Button) sender;
eventButton.FlatAppearance.BorderColor = oldColor;
}
I presume oldColor is a global? This might get out of sync if something "odd" happens where your MouseEnter event is fired for another button, before the corresponding MouseLeave is caught. To make this more robust, I'd consider storing the old color on the Button's .tag property, so that it's self-contained.
Eg:
private void btnWithHoverBorder_MouseEnter(object sender, EventArgs e)
{
Button eventButton = (Button) sender;
eventButton.tag = eventButton.FlatAppearance.BorderColor;
eventButton.FlatAppearance.BorderColor = mouseOverColor;
}
private void btnWithHoverBorder_MouseLeave(object sender, EventArgs e)
{
Button eventButton = (Button) sender;
eventButton.FlatAppearance.BorderColor = (Color)eventButton.tag;
}
(The tag is basically a hook on which to tag "anything" relevant to a specific instance of a control, that there is not already a property for. It's of type Object which means you can tag anything there, but when you read from it, you need to cast it back to whatever type you put there in the first place. But because it's an Object you can put anything there, including eg a custom class that contains multiple properties, or an array, etc if you need to tag a control with more than one thing).

Categories

Resources