I am working on a winform app that requires about 65 radio buttons. I was reading on this forum someone saying that they would not put that many buttons on the designer. Instead have the button show at run time. The problem I had with that is the button were not lined up. Even inside a Panel but they were perfectly lined up when a dragged 65 radio buttons on the designer. Is it a bad Idea to have that many buttons on the design? if so why? Thank you.
I think 65 radio buttons is too much and it doesn't matter if you add them using designer or at run-time and you can use a ComboBox instead.
But if you think you need to use those radio buttons at run-time and the problem for you is aligning them in a column (as you said in comments) so:
you can use a Panel and add radio buttons to the panel and set the Dock of radio buttons to be Top.
Also you can use a FlowLayoutPanel and set a break after adding each radio button.
Also you can use TableLayoutPanel with one column and add radio buttons to the rows.
Example - Using Panel
Add a panel to your form and set it's AutoScroll property true. Then write such code to add radio buttons dynamically to the panel:
//You can have radio texts in a list.
//You can load them from database, file or somewhere else, or define them for example here
var list = new List<string>
{
"First radio text", "Second radio text", "Third radio text", "And so on"
};
this.panel1.SuspendLayout();
for (var i = 0; i < list.Count; i++)
{
var r = new RadioButton();
r.Text = list[i];
r.Tag = i;
r.Name = string.Format("r{0}", i);
r.Dock = DockStyle.Top;
r.CheckedChanged += r_CheckedChanged;
this.panel1.Controls.Add(r);
r.BringToFront();
}
this.panel1.ResumeLayout(true);
And here is the hanlder for CheckedChanged event:
void r_CheckedChanged(object sender, EventArgs e)
{
var radio = (RadioButton)sender;
//Use radio here
//for example int radioIndex = (int)radio.Tag;
//for example if(radio.Checked) ...
}
To access to radio buttons with name, you can use:
//find radio number 26
var radio = (RadioButton)this.panel1.Controls["r25"];
Also you can store radio buttons in a List<RadioButton> when you are adding them to the panel and access them later.
Related
I want to do something like this with windows forms:
Something like tags, but I only want label without colors and "x" value, I just want label with click event, how can I do it without using Telerik? it's not possible to do in datagrid view or something like that? Regards
Tag is a very common .Net property, so the question is bit unclear. But looking at the image and taking a wild guess on what you may want..:
If you want to have the ability to add Labels, let's call them TagLabels during runtime you may want to use a FlowLayoutPanel as their container. It will allow adding more and will take care of the layout no matter what sizes they have.
Example:
To create them we can use a TextBox, which we add to the FLP first. Then we code its PreviewKeyDown event and let the user create a new TagLabel by pressing enter..:
private void textBox1_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
{
if (e.KeyCode == Keys.Enter && textBox1.Text != "")
{
Label lbl = new Label {
Text = " " + textBox1.Text, /* some room for the image */
BorderStyle = BorderStyle.Fixed3D,
TextAlign = ContentAlignment.MiddleCenter,
AutoSize = true,
Margin = new Padding(2),
ImageIndex = flowLayoutPanel1.Controls.Count %
imageList1.Images.Count,
ImageList = imageList1,
ImageAlign = ContentAlignment.MiddleLeft,
MinimumSize = new Size(100, 20),
BackColor = Color.LightGoldenrodYellow,
Name = "TagLabel" + (flowLayoutPanel1.Controls.Count)
};
lbl.MouseClick +=lbl_MouseClick ;
flowLayoutPanel1.Controls.Add(lbl);
flowLayoutPanel1.Controls.SetChildIndex(lbl,
flowLayoutPanel1.Controls.Count - 2);
textBox1.Text = "";
}
else
if (e.KeyCode == Keys.Escape)
{
textBox1.Text = "";
}
}
The Click event should be generic for all labels; so we first cast sender to Label and can then code the processing..:
private void lbl_MouseClick(object sender, MouseEventArgs e)
{
Label lbl = sender as Label;
//...
MessageBox.Show(lbl.Name + " : Ouch! You clicked on " + lbl.Text.Trim());
}
This is just a basic piece of code. You can style the labels any way you want and of course also include code for deleting, maybe with a context menu. If those labels shall carry more responsibility, you can and should create a class, probably a Label subclass to hold further data and methods..
I'm also using an ImageList to display images to the left. Do change these details to suit your needs!
Note that there is no reasonable way to add the FLP to an ordinary DataGridView. You may be able to workaround but depending on your needs it may be best to keep them separate. DGVs have Cells and while these can hold special controls this is complicated and will always be restricted by the cells' i.e. the Columns' and the Rows' Size. As an alternative you can check out this example to see how you can insert virtual space to a row to hold a control but neither DGV nor its Cells are containers.
I am currently creating an online shop on winform in c#.
At the moment I am creating a 'shopping basket' related textbox where if a user clicks on a particular radio button the textbox shows the description of the product in the text box.
I have grouped my radio buttons in a group box and would like to know whether there is anything equivalent to a 'SelectedIndex' command for all radio buttons? Thanks.
Simply subscribe all radio buttons to the same event. Then you can act on which is checked and act accordingly instead of having duplicate code for each button.
Below is a simple example that set a text box's Text property to display which is checked.
Form class
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void radioButtons_CheckedChanged(object sender, EventArgs e)
{
//Do whatever you need to do here. I'm simple setting some text based off
//the name of the checked radio button.
System.Windows.Forms.RadioButton rb = (sender as System.Windows.Forms.RadioButton);
textBox1.Text = $"{rb.Name} is checked!";
}
}
In the .designer.cs file
//Note that the EventHandler for each is the same.
this.radioButton3.CheckedChanged += new System.EventHandler(this.radioButtons_CheckedChanged);
this.radioButton2.CheckedChanged += new System.EventHandler(this.radioButtons_CheckedChanged);
this.radioButton1.CheckedChanged += new System.EventHandler(this.radioButtons_CheckedChanged);
If you want to be able to select more than one radiobutton at a time, I suggest you to use checkboxes instead of radiobuttons. You can assign all their events to the same single event and control which of the checkboxes are checked.
private void checkBox_CheckedChanged(object sender, EventArgs e)
{
CheckBox checkBoxControl = (CheckBox) sender; // You can use this variable to see which one of the checkbox is checked.
}
How do I create a control in a windows form application? I want to generate a textbox or a radio button when I select something from a Combobox. I basically want to query my database, and based on the values of the fields, I want to generate a textbox or a radio button. For example, if my query returns a value of "Textbox", I want to generate a textbox on the form in a specified location. How does one accomplish this? Please help.
The easiest way is to create the control manually in code and then add it to the Controls collection. Deciding which control to create depending on some input data (whether it's database query or a value selected from a combobox) is not much different then in any other case. Simple if will do the job. For instance:
private void AddControl(string control)
{
if (control == "Textbox")
{
TextBox tb = new TextBox();
tb.Location = new Point(100, 100);
this.Controls.Add(tb);
}
else if (control == "Radio")
{
RadioButton rb = new RadioButton();
rb.Location = new Point(200, 100);
this.Controls.Add(rb);
}
}
Of course, it's very naive version. But it's only a starting point. I leave to you adding more advanced logic (like dynamically adjusting location, setting up properties of the radio button or the textbox, relying on Type instead of on a simple string, etc.)
The assumption is that you retrieve a string value from the database. For example in form's constructor:
public Form1()
{
InitializeComponent();
string requestedControl = QueryDatabase();
AddControl(requestedControl);
}
I leave to you implementing the method to query the database.
In the question you also mentioned adding a control after selecting it in the combobox. In this case the only difference is that you rely on an event triggered after combobox's selection changed:
private void comboBox1_SelectedValueChanged(object sender, EventArgs e)
{
string res = this.comboBox1.SelectedItem.ToString();
this.AddControl(res);
}
Here you rely on SelectedValueChanged event. Of course, in this case your combobox has to be populated with expected values (here "Radio" and "Textbox"). Also, you have to attach the event handler to the specific event on the combobox. You can do that in designer or by adding in the constructor the following line:
combobox1.SelectedValueChanged += comboBox1_SelectedValueChanged;
Hope that clarifies the issue and sets up some starting point for you to continue from.
How do you add a button to cells in a row and not the entire column in a datagridview?
I think Adrian's answer was close. Try something like this.
if ((string)table.Rows[0].Cells[0].Value == "I should be a button") {
// you can add formatting or values to the button before assigning it here
table.Rows[0].cells[0] = new DataGridViewButtonCell();
}
I think the best answer if found here:
Hide gridview button. All you need to do is to add a DataGridViewButtonCell where you want buttons, and DataGridViewTextBoxCell where you do not. The column has to be DataGridViewButton type.
See this similar post in SO, probably helps
adding control to gridview
In case Win Form, Check this MSDN post
Column Types in the Windows Forms DataGridView Control
OR this code project post ... though it gives example of adding a image button
DataGridView Image Button Cell
#tmax In that case you can probably put your button creation code in GridView_RowCreated event like below
void GridView_RowCreated(Object sender, GridViewRowEventArgs e)
{
if(e.Row.RowType == DataControlRowType.Header)
{
//Button creation code here
}
}
private void dataGridView1_RowsAdded(object sender, DataGridViewRowsAddedEventArgs e)
{
Button btn = new Button();
//btn attributes
dataGridView1.Rows[0].Cells[3].Value = new Button();
}
try something like this.
What I endded up doing was stacking a DataGridView on top of another one. I turned off the border, gridlines, and scrollbars. Then create dynamic button columns to match the main datagridview with only one row of buttons. Then I used the ColumnWidthChanged event handler to resize both the DataGridViews together. Anyway's this was my workaround for now.
DataGridViewButtonColumn dataGridViewButtonColumn = new DataGridViewButtonColumn();
dataGridViewButtonColumn.Name = "Select";
dataGridViewButtonColumn.HeaderText = "Select";
dataGridViewButtonColumn.ReadOnly = false;
dataGridView1.Columns.Add(dataGridViewButtonColumn);
After assigning data source to gridviewCTRL. you can add new column with button with below code.
DataGridViewButtonColumn startbtn = new DataGridViewButtonColumn();
startbtn.Name = "Action";
startbtn.Text = "Start";
startbtn.UseColumnTextForButtonValue=true;
int columnIndex = 6;
gridviewCTRL.Columns.Insert(columnIndex, startbtn);
This will add the button to each and every row at define column index.
if you want to render condition the AccessibleObject, then you can do something similar to below.
foreach (DataGridViewRow rowdata in gridviewCTRL.Rows)
{
// this is just an example in my case i am checking a previous column value
if (rowdata.Cells[5].Value=="XYZ")
{
rowdata.Cells[6] = new DataGridViewTextBoxCell();
}
}
This way you can dynamically render/ showing the control in the GridView in Winforms c#.
The above code simple update the cell with new cell. We can't remove button from the cell nor remove whole, so instead we can initial a new cell that will override the button visibility.
I am not sure if this will help but you can also consider using TableLayoutPanel.
Refer: Winforms TableLayoutPanel adding rows programmatically
i have 10 textboxes and i need to select text from each one of them.
The problem is that i cant select text from multiple textboxes.
Is there any solution for this problem my code is.
private void Form1_Load(object sender, EventArgs e)
{
createTextBoxes(10);
((TextBox)textBoxes[0]).Select(1, 4);
((TextBox)textBoxes[1]).Select(1, 4); // <- it will not select text
((TextBox)textBoxes[2]).Select(1, 4); // same here
}
Control[] textBoxes;
private void createTextBoxes(int cnt)
{
textBoxes = new Control[cnt];
for (int i = 0; i < cnt; i++)
{
TextBox tb = new TextBox();
tb.Name = i.ToString();
tb.Location = new Point(5, 5 + 14 * i);
tb.Size = new Size(600, 20);
tb.BorderStyle = BorderStyle.None;
tb.Text = "sample text" + i.ToString();
textBoxes[i] = tb;
this.Controls.Add(tb);
}
}
Set the HideSelection property of the texboxes to false. They will maintain selection after losing focus.
Only one control can have a "Focus" at a time... you can't select (ie:highlight) text of multiple controls.
I also just tested by adding a button to the form and posted your 3 "select" snippets there too... nothing showed highlighted. However, when I did a TAB through each control, the first 3 respectfully showed the highlighted section. When I tabbed through the rest, the entire field of the rest of the textboxes were fully selected.
Or are you really trying to accomplish something else...
The text is selected you just can't see it cause of focus.
I ran your code and after doing so tabbed through the controls. The first 3 are selected as specified.
This is possibly not working because even though you've added the TextBox instances to the Form, they have not yet been displayed. Until they are displayed and initially rendered it's likely not possible to initiate a selection on them.
Actually it does, the problem is that the other 2 of your textboxes ([1] and [2]) don't have focus. Only one control can have focus at a time. If you hit tab to give focus to the next TextBox, you'll see the text selected.