Add multiple CommandArguments to button programmatically - c#

I got some code to create new buttons programmatically.
foreach (DataRow dtRow in dtTable.Rows)
{
string question_id = Convert.ToString(dtRow["QUESTION_ID"]);
string question_text = Convert.ToString(dtRow["QUESTION_TEXT"]);
var btn_system = new Button
{
ID = "btn_question" + question_id,
Text = question_text,
CssClass = "quest_buttons"
};
btn_system.Command += ButtonClick_Parent;
btn_system.CommandArgument = Convert.ToString(question_id);
}
Now I would like to add multiple CommandArgument in line 12 of my code snippet. How can I do this from code behind?
Thanks in advance!

You need to pass multiple arguments as a string separating by some character and in event handler, you need to parse them. I have shown here using comma
btn_system.CommandArgument = "argument1,argument2,argument2,...";
then get this using below code
protected void ButtonClick_Parent(object sender, EventArgs e)
{
Button button = (Button)sender;
string[] commandArgs = button.CommandArgument.ToString().Split(',');
}

Related

string values of selected row in datagridview by clicking ANYWHERE in that row

I am using the code below to retrieve values from the selected row it works... but has a glitch.... It will only retrieve the strings if you click on the actual text in any cell of that row.... if you click anywhere of white area in a cell of that row it will not execute .. Any ideas as to how to fix this glitch??
private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
{
listBox1.ClearSelected();
OnlineNamebox.Text = "";
OnlinePasswordbox.Text = "";
OnlineEmailbox.Text = "";
OnlineShortcodebox.Text = "";
ListCombobox.Text = dataGridView1.CurrentRow.Cells[0].Value.ToString();
OnlineNamebox.Text = dataGridView1.CurrentRow.Cells[1].Value.ToString();
OnlineEmailbox.Text = dataGridView1.CurrentRow.Cells[2].Value.ToString();
OnlinePasswordbox.Text = dataGridView1.CurrentRow.Cells[3].Value.ToString();
OnlineShortcodebox.Text = dataGridView1.CurrentRow.Cells[5].Value.ToString();
}
I found a work around for obtaining the cell values based off of dash's answer on a kind of similar question using the cellmouseclick instead of cellclick
with the code below it dont matter where you click at in the row it executes the strings even if not directly clicking on the text in a cell
private void DatagridView1_CellMouseClick(Object sender, DataGridViewCellMouseEventArgs e)
{
ListCombobox.Text = this.dataGridView1.CurrentRow.Cells[0].Value.ToString();
OnlineNamebox.Text = dataGridView1.CurrentRow.Cells[1].FormattedValue.ToString();
OnlineEmailbox.Text = dataGridView1.CurrentRow.Cells[2].Value.ToString();
OnlinePasswordbox.Text = dataGridView1.CurrentRow.Cells[3].Value.ToString();
OnlineShortcodebox.Text = dataGridView1.CurrentRow.Cells[5].Value.ToString();
}
and I added the code below to the load event
dataGridView1.CellMouseClick += DatagridView1_CellMouseClick;
hope it helps anyone who runs into this particular problem or that is looking for the basics

Pass additional variable to button_click() method

I am creating a dynamic table for listing files.
It shows filename, filesize, dateModified columns. In addition, I have added one more columns: Delete.
The method which lists files of a folder in a table.
public void listFile()
{
var dir = new DirectoryInfo(selectedFolder);
Table fileTable = new Table();
foreach (var file in dir.GetFiles())
{
TableRow tr = new TableRow();
TableCell td1 = new TableCell();
TableCell td2 = new TableCell();
TableCell td3 = new TableCell();
TableCell td4 = new TableCell();
Label name = new Label();
Label size = new Label();
Label dateMod = new Label();
LinkButton btn_delete = new LinkButton();
name.Text = file.Name;
size.Text = (file.Length / 1024) + " KB";
dateMod.Text = file.LastWriteTime.ToLongTimeString();
btn_delete.Text = "Delete";
btn_delete.Click += new EventHandler(btn_delete_Click);
td1.Controls.Add(name);
td2.Controls.Add(size);
td3.Controls.Add(dateMod);
td4.Controls.Add(btn_delete);
tr.Controls.Add(td1);
tr.Controls.Add(td2);
tr.Controls.Add(td3);
tr.Controls.Add(td4);
}
filePanel.Controls.Add(fileTable);
}
protected void btn_delete_Click(object sender, EventArgs e)
{
//Delete file
}
Now I want to delete the file when I click on the corresponding delete button. But problem is how will computer know which file to be deleted? I must pass the filename to the delete method.
You can pass command argument to the link button as mentioned below:
btn_delete.CommandArgument = [ID of the file]
and on click event of the link button you can access it as mentioned below:
protected void btn_delete_Click(object sender, EventArgs e)
{
LinkButton btn = (LinkButton)sender;
var id = btn.CommandArgument;
}
Reference: LinkButton.CommandArgument Property
The answer from SpiderCode and RePierre about using the CommandArgument is a correct. It might however help you to understand that the CommandArgument is nothing more than a thin wrapper around the ViewState concept.
ViewState is one way how you can transport data between client and server. If you ever run into a similar problem and you don't have commandargument available you can resort to viewstate.
Take a look at the LinkButton.cs
public string CommandArgument {
get {
string s = (string)ViewState["CommandArgument"];
return((s == null) ? String.Empty : s);
}
set {
ViewState["CommandArgument"] = value;
}
So you can either use the CommandArgument or use ViewState directly.
You can use the CommandArgument property of btn_delete to pass the path to the file:
btn_delete.CommandArgument = file.Name;
And in the event handler you just have to get the value as following:
protected void btn_delete_click(object sender, EventArgs e)
{
var button = sender as Button;
var filename = button.CommandArgument;
}
You can do this by creating a UserControl which is inheritated from the main Control.
In my example I extended a Textbox with an address variable.
In that way you bind a value to the control, which you can use later.
public class ExtendedTextBox : System.Windows.Forms.TextBox
{
private int? _Address = null;
[Description("Address of variable")]
[DefaultValue(null)]
public int? Address
{
get { return _Address; }
set { _Address = value; }
}
}

Saving User Input in a Dynamically Created Form

I'm trying to get the values that a user inputs in a textbox in a dynamically generated form. Another method loads and parses an XML file and creates an object that has specific getters and setters for the settings that it finds in the file (Server, Port, Title, etc.).
The dynamic form is created using labels and textboxes like this. It was designed only to display the information from the XML file, and I am trying to implement a system that allows users to edit the information before saving it again to the file. I'm doing alright with the methods to save and edit the XML file, but I'm lost for how to associate the input in any given textbox with the associated label representing the key in the XML file to change.
Below is the current form implementation where the labels and textboxes are created as part of a foreach loop. I tried creating textbox.Leave eventHandler to track when the user has finished changing a value, but I can't figure out how to know what label it is associated with.
var sortedSettings = new SortedDictionary<string, string>(theSettings.Settings);
int numSettings = sortedSettings.Count;
TextBox[] txt = new TextBox[numSettings];
Label[] label = new Label[numSettings];
int labelSpacing = this.labelSecond.Top - this.labelTop.Bottom;
int textSpacing = this.textBoxSecond.Top - this.textBoxTop.Bottom;
int line = 0;
foreach (KeyValuePair<string, string> key in sortedSettings)
{
label[line] = new Label();
label[line].Text = key.Key;
label[line].Left = this.labelTop.Left;
label[line].Height = this.labelTop.Height;
label[line].Width = this.labelTop.Width;
txt[line] = new TextBox();
txt[line].Text = key.Value;
txt[line].Left = this.textBoxTop.Left;
txt[line].Height = this.textBoxTop.Height;
txt[line].Width = this.textBoxTop.Width;
txt[line].ReadOnly = false;
// Attach and initialize EventHandler for template textbox on Leave
txt[line].Leave += new System.EventHandler(txt_Leave);
if (line > 0)
{
label[line].Top = label[line - 1].Bottom + labelSpacing;
txt[line].Top = txt[line - 1].Bottom + textSpacing;
}
else
{
label[line].Top = this.labelTop.Top;
txt[line].Top = this.textBoxTop.Top;
}
this.Controls.Add(label[line]);
this.Controls.Add(txt[line]);
line++;
}
private void txt_Leave(object sender, EventArgs e)
{
String enteredVal = sender;
FormUtilities.FindAndCenterMsgBox(this.Bounds, true, "EventChecker");
MessageBox.Show("The current value of LABEL is " + enteredVal, "EventChecker");
}
One option is to use TextBox.Tag property.
Example (in foreach loop):
txt[line] = new TextBox();
txt[line].Text = key.Value;
txt[line].Tag = label[line];
To get label associated with TextBox:
TextBox t = txt[0];
Label l = t.Tag as Label;
//Here is how you identify textbox which generated the event.
private void txt_Leave(object sender, EventArgs e)
{
TextBox tb = sender as TextBox;
//..
}

Getting checkbox tags (in a panel) to new form

Rather new to C# so please forgive me if i am missing something simple or am trying to just do this the wrong way.
I am creating another form to compliment my main form and it needs to pull some of the information from Main form on button click of Second form. The information on the Main for is stored in checkboxes and textboxes.
I have the textboxes working fine but cannot figure out how to pull the checkboxes tag data over along with the formatting. Main Form is working fine as is except I cannot figure out how to bring the checkbox data over as well.
This is the code i currently use to display the checkbox TAG data on my main form.
//Statements to write checkboxes to stringbuilder
string checkBoxesLine = "\u2022 LIGHTS ";
foreach (Control control in pnlCheckBoxes.Controls)
{
if (control is CheckBox)
{
CheckBox checkBox = (CheckBox)control;
if (checkBox.Checked && checkBox.Tag is string)
{
string checkBoxId = (string)checkBox.Tag;
checkBoxesLine += string.Format("{0}, ", checkBoxId);
}
}
}
This is the button i am using to open the new form and move the checkbox tag data and textbox.text data to the new form.
private void code_blue_link_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
trouble_shooting = tshooting_text.Text;
services_offered = services_offered_text.Text;
other_notes = other_notes_text.Text;
cust_modem = cust_modem_text.Text;
//Opens CODE BLUE form and pushes text to it.
code_blue_form CBForm = new code_blue_form();
CBForm.cust_name_cb = cust_name_text.Text;
CBForm.cust_cbr_cb = cust_callback_text.Text;
CBForm.cust_wtn_cb = cust_btn_text.Text;
CBForm.cust_notes_cb = cust_modem + "\r\n" + trouble_shooting + "\r\n" + services_offered + "\r\n" + other_notes;
CBForm.Show();
}
Here is my code for the Second form and how i am getting the information to populate textboxes on that form.
public partial class code_blue_form : Form
{
public string cust_name_cb;
public string cust_wtn_cb;
public string cust_cbr_cb;
public string cust_notes_cb;
public string cust_modem_cb;
public code_blue_form()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
cb_name_text.Text = cust_name_cb;
cb_wtn_text.Text = cust_wtn_cb;
cb_cbr_text.Text = cust_cbr_cb;
cb_notes_text.Text = cust_notes_cb;
}
}
}
Please forgive the long post! Any ideas/direction on this would be greatly appreciated. Thanks!
I am not going to answer straight away using ur code. I find code smell. If I were you I would do this (but then if you are adamant about going with the same design, then you can tweak my code accordingly, no big deal, the bottom line is you get the idea how to do):
void code_blue_link_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
var checkBoxIds = GetCheckBoxIds();
cust_modem = cust_modem_text.Text;
trouble_shooting = tshooting_text.Text;
services_offered = services_offered_text.Text;
other_notes = other_notes_text.Text;
//take off underscore convetion and replace with camelCase convention.
CodeBlueForm cbForm = new CodeBlueForm(checkBoxIds, cust_name_text.Text,
cust_callback_text.Text,
cust_btn_text.Text,
cust_modem + "\r\n" +
trouble_shooting + "\r\n" +
services_offered + "\r\n" +
other_notes);
cbForm.Show();
}
private List<int> GetCheckBoxIds()//even better naming required like GetFruitIds()
{ //(whatever the id is of) or even better Tag
//checkBoxes with the Fruit object iself and not ids.
List<int> checkBoxIds = new List<int>(); //So you can call GetFruits();
foreach (Control control in pnlCheckBoxes.Controls)
{
if (control is CheckBox)
{
CheckBox checkBox = (CheckBox)control;
if (checkBox.Checked && checkBox.Tag is int) //tag them as ints.
checkBoxIds.Add((int)checkBox.Tag); //I hope ids are integers.
}
}
return checkBoxIds;
}
public partial class CodeBlueForm : Form
{
List<int> checkBoxIds = new List<int>():
string cust_cbr_cb; //should be private.
string cust_name_cb;
string cust_wtn_cb;
string cust_notes_cb;
string cust_modem_cb;
public CodeBlueForm(List<int> ids, string cust_name_cb, string cust_wtn_cb,
string cust_notes_cb, string cust_modem_cb)
{
InitializeComponent();
this.checkBoxIds = ids;
this.cust_name_cb = cust_name_cb;
this.cust_wtn_cb = cust_wtn_cb;
this.cust_notes_cb = cust_notes_cb;
this.cust_modem_cb = cust_modem_cb;
}
private void button1_Click(object sender, EventArgs e)
{
cb_name_text.Text = cust_name_cb;
cb_wtn_text.Text = cust_wtn_cb;
cb_cbr_text.Text = cust_cbr_cb;
cb_notes_text.Text = cust_notes_cb;
string checkBoxesLine = "\u2022 LIGHTS ";
// if you dont require a lot of string formatting, then just:
checkBoxesLine += string.Join(", ", checkBoxIds);
// or go with your classical:
//foreach (int id in checkBoxIds)
// checkBoxesLine += string.Format("{0}, ", checkBoxIds);
//and do what u want with checkboxline here.
}
}

Dynamic control and its Event

We are creating dynamic text boxes and buttons inside a grid for each row. Now we want to create click event for each button. To create button inside the grid in using ITemplate.
Code:
ImageButton imbtnAdd = new ImageButton();
imbtnAdd.ID = "imbtn" + columnName;
imbtnAdd.ImageUrl = "btn_add_icon.gif";
imbtnAdd.Width = 20;
container.Controls.Add(imbtnAdd);
Error:
I have used imbtnAdd.Click += new ImageClickEventHandler(imbtnAdd_Click); but it shows an error message
imbtnAdd_Click does not exist
ImageButton imbtnAdd = new ImageButton();
imbtnAdd.ID = "imbtn" + columnName;
imbtnAdd.ImageUrl = "btn_add_icon.gif";
imbtnAdd.Width = 20;
imbtnAdd.Click += imbtnAdd_Click;
container.Controls.Add(imbtnAdd);
// ...
private void imbtnAdd_Click(object sender, EventArgs e)
{
// handle event
}
Jrista's answer is correct.
Although, if you want to implement different handlers for all the buttons and you are using .Net 3.0 or above, you can use lambdas:
imbtnAdd.Click += (object sender, EventArgs e) =>
{
// Code handling code goes here...
};

Categories