I have a form which initially has one row of boxes for user input. I have a button which, when clicked, should create an identical row below the previous. The button should be able to be clicked more than once, to add multiple rows.
How can I go about implementing this, in a way which gives each control in each row its own unique name (so I can refer to it in my program), and also keeping proper formatting of the rows?
I have tried to set up a class for rows as below:
class SubjectRow
{
//every row has these boxes, plus some more textboxes
public ComboBox subjectBox;
public Label maxBox;
public TextBox aBox;
public SubjectRow(ComboBox _subjectBox, Label _maxBox, TextBox _aBox)
{
subjectBox = _subjectBox;
maxBox = _maxBox;
aBox = _aBox;
}
}
...But I am stumped on how to have the button generate the new controls with their own names. My idea was something like this:
buttonClicked
{
SubjectRow row1 = new SubjectRow(subjectBox1, maxBox1, aBox1);
}
But I need a way to change the control names here without manually typing them all out; there could possibly be a lot of rows on the form.
Is there a way to add more rows to my form using a button, giving each control in each row a unique name? This needs to be done in some kind of loop.
Related
I've working on a C# Forms application, the MainScreen contains a DataGridView in which the first row is an auto-generated incremented number. When manually coding data into the DataGridView, I'm able to set this ID field with the incremented number.
What I'm trying to do now is create an "Add" form, I need the first text box to be populated with the next incremented number when it opens.
What is the simplest way to know what the current last number used in the DataGridView is?
For example, if I have 2 rows, obviously the new "Add" row would have an ID of 3, but how can I code the Text box to dynamically grab that information and increment +1 each time the form is opened?
Edit:
To provide more context, I will have a button for Add, and a button for Modify. The modify button will not open the Modify form unless a row is selected. Here is my code to populate the text box on the modify form, based on the selected row:
ModPartIDBox.Text = Inventory.AllParts[Inventory.CurrentIdxPrt].PartID.ToString();
The "Add" form obviously doesn't check and doesn't care if a row is selected, so I can't lean on just calling that already filled field, so I just need a way to grab highest number.
Keep a list of all objects that you are going to store in your DataGridView so you can access their data later on, such as:
var items = new List<MyObject> {}
Where MyObject looks a little something like this:
public class MyObject
{
public int PartId { get; set; }
}
and then when you need to pull the highest number, you can use a LINQ expression:
int highestNumber = items.OrderByDescending(x => x.PartId).First().PartId;
I'm running into a problem making multiple selections programmatically in a DataGridView (DGV) based on data table values. I have a table with one column "ID", I need to pass these values to another form with a DGV for editing, ID is the first DGV column also, i.e. for every ID in the table, the appropriate DGV row should be selected.
I can loop through the table and DGV fine, but only the last value is selected even though the DGV properties MultiSelect=true ... when I use the form manually, multiple select works fine.
foreach(DataRow dtrow in dt.Rows)
{
string Selection = dtrow["ID"].ToString();
foreach(DataGridViewRow DGVrow in dgview.Rows)
{
if (DGVrow.Cells[0].Value.ToString().Equals(Selection))
{
dgview.CurrentCell = DGVrow.Cells[0];
int cellInx = dgview.CurrentCell.RowIndex;
dgview.Rows[cellInx].Selected = true;
break;
}
}
}
I'm answering my own question because I don't think this is possible on form load. My application has a form that's used to add selections to a project. When the user wants to 'Edit' the project, I need to call this form and make all the previous selections so the user can add/delete.
When using a DataGridView (DGV) with multi-select enabled, at run time, you can 'ctl-click' and select multiple items ... essentially I'm trying to recreate this behavior in code, on form load in 'edit' mode.
After the form is initialized I have a method that loads the DGV from OleDb tables, to test this out I tried putting the following lines after the load method call and as the last lines of the method call:
dgv1.Rows[0].Selected = true;
dgv1.Rows[1].Selected = true;
dgv1.Rows[2].Selected = true;
Obviously, on form load, I was expecting the first 3 rows to be 'selected', but that didn't happen.
However, I remembered a separate issue, I could never get the DGV to load without the first line selected by default ... so I put in a 'refresh' button, that simply calls the 'Load' method again ... the last line of which is: DGV1.Rows[0].Selected = False; With the refresh button the DGV loads without the first line selected.
I was curious if this was a similar situation, so when I added these 3 lines to the end of the load method, nothing happened on form load ... but ... when I hit the 'Refresh' button, the first 3 rows were 'selected'.
I've been researching this for over 3 days and found the following from the DataGridView Project Manager (2006):
https://social.msdn.microsoft.com/Forums/windows/en-US/cf351d44-4a9a-4c80-8d52-4fb349847908/multiple-select-is-not-working-for-datagridview?forum=winformsdatacontrols
Unfortunately there isn’t an easy solution to this as I didn’t look at this scenario and design the grid to handle this well. The main problem stems from the fact that when you mouse down on the grid, the grid sets the current cell property which clears the selection before selecting the next cell/row/column. So, while your line of code selects the row, when you go to select the next row or just move to the next row using the keyboard, the row you selected is cleared. The easiest way to do your scenario is to use custom painting via the RowPrePaint and paint the “selected” rows using the same SelectedBackground color. You can just query the value of the check box cell in the row that you are painting to know if that row is “selected”, but there isn’t any need to set the Selected property to true. The flip side to this is that you’ll have to keep track or enumerate all rows to know all the “selected” row at a given time.
-> mark -> DataGridView Program Manager - 2006
So my plan going forward is to rebuild the DGV to use check boxes, as recommended. I just wanted to put this out there for general information and/or if someone has a better idea. Thanks
I have a simple DataGridView:
I have a class:
public class TemplateItem
{
public string Name { get; set; }
public decimal Price { get; set; }
}
And a list to store templates:
List<TemplateItem> templates = new List<TemplateItem>();
// Some code to populate the list
For the "Name" cell in the grid, I want to:
display autocomplete options from the templates list when the user types in the cell
automatically set the "Price" cell to the price of the autocomplete option that the user has selected (the user can change the price afterwards)
allow the user to type in something not available in the templates list
I know how to enable autocomplete by using EditingControlShowing event, like in this question.
I don't know how to detect the selection of an autocomplete option. Using KeyDown event doesn't work for me - it never fires.
And I don't know how to get the price of the selected option. Supposing I was able to catch the "option selected" event, I could go through the templates and find the one with the same name... but that seems ugly code to me. I should be able to pass the information about the price for each option somehow, right?
I ended up re-modifying my user interface, so that the grid no longer allows the user to enter new rows. Instead, I have a separate ComboBox (DropDownStyle set to DropDown) with autosuggest turned on and an "add" button to insert new rows based on the value from the combobox. If an existing template is selected, its price is inserted as well; otherwise, just the entered text is inserted.
If anyone knows of how to achieve the same functionality within the datagridview, please let me know.
The last column in my Datagrid is hyperlinked, every cell has an individual hyperlink. I want to be able to click on a cell, get the data within that cell, and using the hyperlink, redirect to another form, passing that data selected.
string AuditsRequired = (dgFake.Items[0] as DataRowView).Row.ItemArray[5].ToString();
xamlAllocteAudits AA = new xamlAllocteAudits(AuditsRequired);
AA.Show()
This is my first attempt at fetching the cell-data, however due to the code, I have specified a column and row, whereas I want the cell to be which ever cell I click, rather than specifying in code.
Here is my datagrid, showing the cells that have been hyperlinked:
http://i.stack.imgur.com/v7Uyw.png
If i understand your question correctly, you want to click on a cell and obtain the data from that cell. I suspect that the cellclicked event or currentcellchanged event are going to be the most useful to you for this task.
you could try something like
private void dgFake_CurrentCellChanged(object sender, EventArgs e)
{
int row = e.row;
int col = e.col;
if e.value !=null
{
string AuditsRequired = dgfake[row,col].value.tostring();
xamlAllocteAudits AA = new xamlAllocteAudits(AuditsRequired);
AA.Show()
}
}
You may or may not know this, but you can get VS to make this event method (or any event method) for you by clicking on the object (in your case the datagridviewer) in the designer and then clicking the events (little lightning bolt) icon in the properties window.
Hope that helps.
Cheers.
I want to add a new row to a datagridview such that when a user clicks on new button , a new is is generated with few textboxes and combo boxes and after filling up all the details he save the info by clicking on save button.
EDIT
I want to do it like it is seen in gridview(Template Fields) in asp.net
I am looking for same kind of functionality.
Since I'm not sure exactly how you want to achieve this.. I would have a hidden panel with your text boxes, ...etc, show the panel when the new button is clicked. After all information is entered into the fields, click the save button. Assuming that you will be inserting this information into a table, after the row is inserted, call the stored procedure to get the desired records from the table being displayed in the grid.
Assuming your _dataGridView.Columns collection is not null and contains a template of the rows you wish to add, it is as simple as something like this:
foreach(var item in _collection)
{
_dataGridView.Rows.Add(item.Foo, item.Bar);
}
In order for this to work, you will have had to design your Columns collection in the VisualStudio designer or programatically add DataGridViewTextBoxColumn objects to the Columns collection.
In the example above, I added two DataGridViewTextBoxColumn objects to the _dataGridView.Columns collection and then populated the datagrid from a List of my object that contained a 'Foo' and a 'Bar'.
EDIT
Have you checked out the DataGridView FAQ? The information about using the DataGridView in unbound mode may help you.
HTH