I'm trying to implement a submit button to where the user inputs their information in 3 textboxes and when they click on the submit button, the information gets stored into a list which allows me to add it to an object that I have created.
I have tried creating a temporary list, the first index seems to display fine, but I'm really struggling to understand how to add onto the list and how to make it so when they click on 'submit' again, it stores in the next index.
Every time I click on submit, it contentiously stores in the first index.
private Fleet boatOne;
private Fleet boatTwo;
private Fleet boatThree;
private Fleet boatFour;
private void BoatSubmitButton_Click(object sender, EventArgs e)
{
List<string> tempTextBox = new List<string>();
tempTextBox.Add(BoatNameTextBox.Text);
tempTextBox.Add(BoatNameTextBox.Text);
string licenseVariable = BoatLicenseTextBox.Text;
string intVariable = MaximumLoadTextBox.Text;
boatOne = new Fleet(tempTextBox[0], licenseVariable, intVariable);
BoatNameTextBox.Text = boatOne.GetboatName();
BoatLicenseTextBox.Text = boatOne.GetboatLicense();
MaximumLoadTextBox.Text = boatOne.GetmaximumLoad();
boatTwo = new Fleet(tempTextBox[1], licenseVariable, intVariable);
BoatNameTextBox.Text = boatTwo.GetboatName();
BoatLicenseTextBox.Text = boatTwo.GetboatLicense();
MaximumLoadTextBox.Text = boatTwo.GetmaximumLoad();
BoatNameTextBox.Text = "";
BoatLicenseTextBox.Text = "";
MaximumLoadTextBox.Text = "";
Also, when I click on the submit button, not only do I want it storing the information into an object, but I want the object to display properly into my DataGridView.
DataTable dt2 = new DataTable();
dt2.Columns.Add("Boat Name");
dt2.Columns.Add("License Number");
dt2.Columns.Add("Maximum Load");
dt2.Rows.Add(new object[] { boatOne.GetboatName(), boatOne.GetboatLicense(), boatOne.GetmaximumLoad() });
dt2.Rows.Add(new object[] { boatTwo.GetboatName(), boatTwo.GetboatLicense(), boatTwo.GetmaximumLoad() });
dt2.Rows.Add(new object[] { boatThree });
dt2.Rows.Add(new object[] { boatFour });
BoatDataGridView.DataSource = dt2;
BoatDataGridView.CellBorderStyle = DataGridViewCellBorderStyle.None;
BoatDataGridView.RowHeadersVisible = false;
BoatDataGridView.AutoResizeColumns();
BoatDataGridView.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
FishDataGridView.AutoResizeColumns();
FishDataGridView.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
This can be done with nearly no code (written by you I mean) at all:
right click your project in solution explorer
add a new item
make it a DataSet, give it a suitable name
on the design surface for the dataset right click and choose Add New.. DataTable
name it Fleet (personally I would name it Boat but..)
right click it and add columns for name, license number etc
save the set
open the forms designer
show the Data sources window (view menu >> other windows >> data sources)
expand the datset node
drag the Fleet node into the forms designer
expand the fleet node
drag all the children of it to the forms designer too
You now have text boxes and a grid, data bound to the same dataset. You also have a menu bar type thing with an add button and some navigators etc
Run the program. You can either type in the grid cells or the text boxes. You can use the nav buttons or click different rows in the grid to change the current row
If you want to add elements to a list and then update a DataGridView, then you don't need the individual Fleet elements. Just one List(Of Fleet)
private List<Fleet> myBoats = new List<Fleet>();
....
private void BoatSubmitButton_Click(object sender, EventArgs e)
{
Fleet boat = new Fleet(BoatNameTextBox.Text, BoatLicenseTextBox.Text, MaximumLoadTextBox.Text;);
myBoats.Add(boat);
BoatDataGridView.DataSource = null;
BoatDataGridView.DataSource = myBoats;
BoatNameTextBox.Text = "";
BoatLicenseTextBox.Text = "";
MaximumLoadTextBox.Text = "";
}
However, you could use a simplified approach if you bind your DataGridView to a BindingList instead of a simple List. The BindingList object has the ability to automatically refresh the binded object
public void Form1_Load(object sender, EventArgs e)
{
BoatDataGridView.DataSource = new BindingList<Fleet>();
}
private void BoatSubmitButton_Click(object sender, EventArgs e)
{
Fleet boat = new Fleet(BoatNameTextBox.Text, BoatLicenseTextBox.Text, MaximumLoadTextBox.Text;);
BindingList<Fleet> bs = BoatDataGridView.DataSource as BindingList<Fleet>;
bs.Add(boat);
BoatNameTextBox.Text = "";
BoatLicenseTextBox.Text = "";
MaximumLoadTextBox.Text = "";
}
List<Fleet> boatList = new List<Fleet>();
DataTable dt2 = new DataTable();
private Fleet currentBoat;
private int boats = 0;
private void BoatSubmitButton_Click(object sender, EventArgs e)
{
string licenseVariable = BoatLicenseTextBox.Text;
string intVariable = MaximumLoadTextBox.Text;
if (BoatNameTextBox.Text == "")
{
MessageBox.Show("Please Input Name", "ERROR", MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
else
{
boatList.Add(new Fleet(BoatNameTextBox.Text, licenseVariable,
intVariable));
currentBoat = boatList[boats];
dt2.Rows.Add(new object[] { currentBoat.GetboatName(),
currentBoat.GetboatLicense(), currentBoat.GetmaximumLoad() });
}
BoatNameTextBox.Text = "";
BoatLicenseTextBox.Text = "";
MaximumLoadTextBox.Text = "";
boats++;
}
Related
I have a form application where multiple DataGridView objects are to be displayed (but not at once). They should be created on top of each other and it should then be possible to toggle the displayed DataGridView using a ComboBox.
I have a function which should create new DataGridView every time its called and then adds the name to the ComboBox:
private void readCSV(string DBname)
{
DataGridView tagDBname = new DataGridView();
tagDBname.Location = new System.Drawing.Point(24, 260);
tagDBname.Name = DBname;
tagDBname.Size = new System.Drawing.Size(551, 217);
tagDBname.TabIndex = 6;
tagDBname.Columns.Add("Column1", "Col1");
tagDBname.Columns.Add("Column2", "Col2");
tagDBname.Visible = false;
comboBoxTag.Items.Add(DBname);
}
Then I would like to change the visibility state of a DataGridView given the selected name from the ComboBox. This should be done in the function called when the index changes:
private void comboBoxTag_SelectedIndexChanged(object sender, EventArgs e)
{
// Get the name of the DataGridView which should be visible:
string selectedTagDB = comboBoxTagDatabases.SelectedItem.ToString();
DataGridView tagDatabase = ? // Here the DataGridView should be selected given the name "selectedTagDB"
tagDatabase.Visible = true;
}
In the above, I do not know how to assign the DataGridView only given its name. Any help would be appreciated - even if it means that the selected approach is inappropriate of what I am trying to achieve. If the question is answered elsewhere, feel free to guide me in the right direction :)
I would store the gridviews in a dictionary by using the DB name as key;
private readonly Dictionary<string, DataGridView> _tagDBs =
new Dictionary<string, DataGridView>();
private void readCSV(string DBname)
{
DataGridView tagDBname = new DataGridView();
// Add the gridview to the dictionary.
_tagDBs.Add(DBname, tagDBname);
tagDBname.Name = DBname;
tagDBname.Location = new System.Drawing.Point(24, 260);
tagDBname.Size = new System.Drawing.Size(551, 217);
tagDBname.TabIndex = 6;
tagDBname.Columns.Add("Column1", "Col1");
tagDBname.Columns.Add("Column2", "Col2");
tagDBname.Visible = false;
this.Controls.Add(tagDBname); // Add the gridview to the form ot to a control.
comboBoxTag.Items.Add(DBname);
}
private void comboBoxTag_SelectedIndexChanged(object sender, EventArgs e)
{
// Get the name of the DataGridView which should be visible:
string selectedTagDB = comboBoxTagDatabases.SelectedItem.ToString();
foreach (DataGridView dgv in _tagDBs.Values) {
dgv.Visible = dgv.Name == selectedTagDB; // Hide all gridviews except the selected one.
}
}
If you need to do something with the selected gridview, you can get it with:
if (_tagDBs.TryGetValue(selectedTagDB, out DataGridView tagDatabase)) {
// do something with tagDatabase.
}
Note: you must add the gridview to the form or to a container control on the form. E.g.
this.Controls.Add(tagDBname);
You can loop through all DataGridViews of the form to display the expected one using its name, while hidding the others ones.
This solution isn't pretty but works
private void ShowOneDataGridViewAndHideOthers(string name)
{
foreach (var DGV in this.Controls.OfType<DataGridView>())
{
DGV.Visible = DGV.Name == name;
}
}
And call it this way :
private void comboBoxTag_SelectedIndexChanged(object sender, EventArgs e)
{
// Get the name of the DataGridView which should be visible:
string selectedTagDB = comboBoxTagDatabases.SelectedItem.ToString();
ShowOneDataGridViewAndHideOthers(selectedTagDB);
}
The method can be made a bit more generic this way :
private void ShowOneControlAndHideOthers<T>(string name, Control controls) where T : Control
{
foreach (var control in controls.Controls.OfType<T>())
{
control.Visible = control.Name == name;
}
}
private void comboBoxTag_SelectedIndexChanged(object sender, EventArgs e)
{
// Get the name of the DataGridView which should be visible:
string selectedTagDB = comboBoxTagDatabases.SelectedItem.ToString();
ShowOneControlAndHideOthers<DataGridView>(selectedTagDB, this);
}
I am working on a Windows application where I get an input from a TextBox and add it to the DataGridView when user clicks on a Button (Add).
My problem is that when I add the text for the first time, it works fine and its added to the grid.
When I add new text, it's not added to the DataGridView. Once the Form is closed and reopened with the same object then I am able to see it.
Code:
private void btnAddInput_Click(object sender, EventArgs e)
{
if (Data == null)
Data = new List<Inputs>();
if (!string.IsNullOrWhiteSpace(txtInput.Text))
{
Data.Insert(Data.Count, new Inputs()
{
Name = txtInput.Text,
Value = string.Empty
});
}
else
{
MessageBox.Show("Please enter parameter value", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
txtInput.Text = "";
gridViewInputs.DataSource = Data;
}
I am not sure what is causing the record not to be added to grid on second add button click.
You could set the DataGridView.DataSource to null before setting a new one.
This would cause the DataGridView to refresh its content with the new data in the source List<Inputs>:
the underlying DataGridViewDataConnection is reset only when the DataSource reference is different from the current or is set to null.
Note that when you reset the DataSource, the RowsRemoved event is raised multiple times (once for each row removed).
I suggest to change the List to a BindingList, because any change to the List will be reflected automatically and because it will allow to remove rows from the DataGridView if/when required: using a List<T> as DataSource will not allow to remove a row.
BindingList<Inputs> InputData = new BindingList<Inputs>();
You can always set the AllowUserToDeleteRows and AllowUserToAddRows properties to false if you don't want your Users to tamper with the grid content.
For example:
public class Inputs
{
public string Name { get; set; }
public string Value { get; set; }
}
internal BindingList<Inputs> InputData = new BindingList<Inputs>();
private void Form1_Load(object sender, EventArgs e)
{
dataGridView1.DataSource = InputData;
}
private void btnAddInput_Click(object sender, EventArgs e)
{
string textValue = txtInput.Text.Trim();
if (!string.IsNullOrEmpty(textValue))
{
InputData.Add(new Inputs() {
Name = textValue,
Value = "[Whatever this is]"
});
txtInput.Text = "";
}
else
{
MessageBox.Show("Not a valid value");
}
}
If you want to keep using a List<T>, add the code required to reset the DataGridView.DataSource:
private void btnAddInput_Click(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(textValue))
{
//(...)
dataGridView1.DataSource = null;
dataGridView1.DataSource = InputData;
txtInput.Text = "";
}
//(...)
I have dynamic drop down lists that are created based on what's selected in the list box.. When clicking confirm this is when the drop down lists are created. Clicking save is where I attempt to retrieve the values. However I am unable to retrieve that values that are in the drop down lists.
Code:
protected void btnConfirm_Click(object sender, EventArgs e)
{
int ID = 0;
foreach (string value in values)
{
MyStaticValues.alEdit.Add(value);
CreateEditForm(value, ID);
ID += 1;
}
if (values.count != 0)
{
btnSave.Visible = true;
btnConfirm.Enabled = false;
}
}//End of btnConfirm_Click
protected void CreateEditForm(string Value, int ID)
{//Creates an edit form for the value inserted.
string name = value;
//This part adds a header
phEditInventory.Controls.Add(new LiteralControl("<h2>" + name + "</h2>"));
phEditInventory.Controls.Add(new LiteralControl("<div class=\"clearfix\"></div>"));
//Create a label
Label lblName = new Label();
lblName.Text = "Name";
lblName.ID = "lblName" + ID;
lblName.CssClass = "control-label";
//Create a Drop Down List
DropDownList ddlName = new DropDownList();
ddlName.ID = "ddlName" + ID;
ddlName.CssClass = "form-control";
//Set default N/A Values For Drop Down List
ddlName.Items.Add(new ListItem("N/A", Convert.ToString("0")));
//The Rest of the Values are populated with the database
//Adds the controls to the placeholder
phEditInventory.Controls.Add(lblName);
phEditInventory.Controls.Add(ddlName);
phEditInventory.Controls.Add(new LiteralControl("<div class=\"clearfix\"></div>"));
} //End of CreateEditForm
protected void btnSave_Click(object sender, EventArgs e)
{
string name = "";
try
{
for (int i = 0; i < MyStaticValues.alEdit.Count; i++)
{
string nameID = "ddlName" + i.ToString();
DropDownList ddlName = (DropDownList)phEditInventory.FindControl(nameID);
name = ddlName.SelectedValue.ToString();
}
}
catch (Exception ex)
{
}
phEditInventory.Visible = false;
btnSave.Visible = false;
MyStaticValues.alEdit.Clear();
}//End of btnSave_Click Function
Your problem is that the dynamically created dropdown lists are not maintained on postback. When you click the Save button, a postback occurs, and the page is re-rendered without the dynamically created dropdowns. This link may help.
Maintain the state of dynamically added user control on postback?
i am trying a few things in WinForms for the first time. I have a problem which appears very trivial to me but then i am not a WinForms guy.. searched a lot but could not find the solution.
Below is the code, don't worry about the content itself, its just test code. The problem is that when i click the AddNew button a row gets added to gridview but after that no row gets added, no matter how many times user clicks on the AddNew button. You can see that in the Image below.
Can you point out why no rows are getting added to the gridview after a row has been added.
AddNew button just works for one click. While as it should add the second row again and again.
Thanks in advance.
public partial class JobCard : UserControl
{
List<Work> works = new List<Work>();
BindingSource bs = new BindingSource();
public JobCard()
{
InitializeComponent();
works.Add(new Work() { S_No = 1, JobCategoryId = 1, JobCategoryName = "electricals", JobId = 1, JobName = "lights", Labour = 1, MaterialName = "tape", PartName = "headlight" });
bs.DataSource = works;
dataGridView1.AutoGenerateColumns = true;
dataGridView1.DataSource = bs;
}
private void btnAddNew_Click(object sender, EventArgs e)
{
works.Add(new Work() { S_No = 2, JobCategoryId = 2, JobCategoryName = "electricals", JobId = 2, JobName = "lights", Labour = 2, MaterialName = "tape", PartName = "headlight" });
dataGridView1.DataSource = works;
}
}
You need to reset the datasource of your bindingsource.
Try
private void btnAddNew_Click(object sender, EventArgs e)
{
...
bs.DataSource = null;
bs.DataSource = works;
}
In my Windows application I had a job code combobox and when user selects a jobcode from the combobox it will get the corresponding data from database and will display it in a datagridview below the combobox. All is fine and I am able to load data corresponding to selected jobcode.
I used the this code
public void loadcompljobcodecombobox()
{
completedcobcodeadapterTableAdapter cmpltjbcd = new completedcobcodeadapterTableAdapter();
cmpltjbcd.Connection = new OleDbConnection(Program.ConnStr);
DataTable dt= cmpltjbcd.GetData(int.Parse(cmbcutcode.SelectedValue.ToString()));
if (dt.Rows.Count > 0)
{
cmbjobcode.ValueMember = "jobpk";
cmbjobcode.DisplayMember = "jobcode";
txtcompanyname.Text = "companyname";
cmbjobcode.DataSource = dt;
}
else
{
MessageBox.Show("NO JobCode to be invoiced");
}
}
private void cmbjobcode_SelectedValueChanged(object sender, EventArgs e)
{
tbltoinvoicedtableTableAdapter tbltoinvce = new tbltoinvoicedtableTableAdapter();
tbltoinvce.Connection = new OleDbConnection(Program.ConnStr);
if (cmbjobcode.SelectedValue != null)
{
DataTable dt = tbltoinvce.GetDataBy(int.Parse(cmbjobcode.SelectedValue.ToString()));
dataGridView1.DataSource = dt;
}
}
Now my requirement is user must be able to select more than one jobcode details at a time for invoicing i.e. if he selects one value from jobcode corresponding data should be added in datagridview and when he select another jobcode its corresponding data should be added as next row in the Datagridview.
I had tried very much and find no way can anyone suggest an idea or example
If I understand you correctly, I would try something like this. This isn't tested but it's an idea.
At Form Level:
private BindingList<DataRow> jobList;
Then to add to your current code...
private void cmbjobcode_SelectedValueChanged(object sender, EventArgs e)
{
tbltoinvoicedtableTableAdapter tbltoinvce = new tbltoinvoicedtableTableAdapter();
tbltoinvce.Connection = new OleDbConnection(Program.ConnStr);
if (cmbjobcode.SelectedValue != null)
{
DataRow job = tbltoinvce.GetDataBy(int.Parse(cmbjobcode.SelectedValue.ToString())).Rows[0];
if (jobList == null)
{
jobList = new BindingList<DataRow>();
jobList.Add(job);
dataGridView1.DataSource = jobList;
}
else
{
if (!jobList.Contains(job));
jobList.Add(job);
}
}
}
**Edit: This is assuming your job data contains only one row of data since your question asked for how to add "a row".