How can I get the rearranged columns out of a datagridview in C#? I need to get all the columns currently being displayed in order. I can get the default columns order by setting datagridview.AutoGenerateColumns=false but I get the same old order even after I've rearranged the columns in my table.
Edit: Basically what I need is to be able to iterate through all the columns of a datagridview based on their display index
Thanks
Use the DisplayIndex property of your DataGridView Columns.
The DisplayIndex property:
Gets or sets the display order of the
column relative to the currently
displayed columns.
Edit:
It's ugly, and I'm sure people are going to point and laugh, but this might give you a rough idea on one implementation to improve upon.
Create a DGV with three columns and set their DisplayName properties like so:
dataGridView1.Columns[0].DisplayIndex = 1;
dataGridView1.Columns[1].DisplayIndex = 2;
dataGridView1.Columns[2].DisplayIndex = 0;
Add the following code to loop through all the columns access the columns in the DGV in their DisplayIndex order:
for (int index = 0; index < dataGridView1.Columns.Count; index++) {
foreach (DataGridViewColumn c in dataGridView1.Columns) {
if (c.DisplayIndex == index) {
// You've got your next column.
Console.WriteLine(c.Name);
}
}
}
How are you selecting? SELECT *? You need to specify the columns in the order you want them.
Have you rearranged their order in the ItemTemplate section of your grid? You can also change the order via the context menu for a GridView, alternative you can change your SQL statement and make sure autogenerate is off
Related
I want to edit column title in datagridview using Entity Framework. I added column and design name with form design, but when I add datasource in code, the columns with data appear in the left, and the columns I created with form design appear with blank. How can I use column design name to fill data from datasource?
I tried many things like
column[0].headercell.value = "column title"
but I don't want that. I want to use column design name.
Based on my test, I reproduced your problem. I suggest that you could give up datagridview1.DataSource=context.students.ToList().
If you only need to show the columns that you edited in winform, I recommend that you could use reflection and loop to do it.
Here is a code example you could refer to.
private void Form1_Load(object sender, EventArgs e)
{
Model1 model = new Model1();//DbContext
foreach (var item in model.Students)
{
dataGridView1.Rows.Add();
}
var columns = dataGridView1.Columns;
for (int i = 0; i < dataGridView1.ColumnCount; i++)
{
var names = model.Students.ToList().Select(x => x.GetType().GetProperty(columns[i].Name).GetValue(x)).ToList();
for (int j = 0; j < names.Count(); j++)
{
dataGridView1.Rows[j].Cells[dataGridView1.Columns[i].Name].Value = names[j].ToString();
}
}
}
Tested result(Only show the Id and Age column):
You should almost never give up setting DataSource.
As mentioned in the first comment under the answer, if you set DataPropertyName for the column, then it will not be added again after setting data source.
Even if you want to only show a few of the columns, just add them to the DataGridView columns collection, and make sure you set AutogenerateColumns to false, to prevent adding undesired columns.
If you do not wan to add the columns manually or set the header texts manually, then you can decorate the property with [Browsable(false)] to prevent showing the column in DataGridView, and useing [DisplayName("The title")] attribute to assign header text.
And finally you may be interested in the following posts:
DataAnnotations attributes for DataGridView in Windows Forms
DataAnnotation Attribute in Windows Forms - How to use UIHint Attribute with WinForms, an extension to my other answer to ad support for UIHint to specify column type.
I have DevExpress GridControl with one default GridView to show the records in my form. I have bound the values to GridControl from SQL Database table. Here, I want to select the single column's values as array or something similar using mouse click with any key combination. I have googled and get the solution to select multiple rows using CheckBox column.
But, my scenario is different. I would like to select single column's values as array.
EDIT:
I am also looking for an answer which needs to be highlight all cell values when clicked with any key combination in column header (similar like we have an option in Microsoft Excel).
Thanks in advance.
I don' think that there is a built-in method to do that. You can loop through rows and use ColumnView.GetRowCellValue to access the cells from a particular column.
Something like this should work:
//get the number of rows in a target view (gridView for example)
int rowsCount = gridView.DataRowCount;
//allocate an array for column values
var columnValues = new object[rowsCount];
//get column by field name
var column = gridView.Columns["ColumnName"];
//loop through rows and populate column values
for (int rowIndex = 0; rowIndex < rowsCount; rowIndex++)
{
columnValues[rowIndex] = gridView.GetRowCellValue(rowIndex, column);
}
UPDATE: You can refer to the official example in DevExpress knowledge base: How to select cells under by clicking the GridBand or the column header.
What you'll need to do:
handle MouseDown event on a gridview;
use CalcHitInfo to detect a click on a column header (check out this question: "Detect the column header region in the mouse down event of a grid)" and this knowledge base article: "Hit Information";
then use GridView.SelectCell to update selection
private void SelectCells(GridColumn column) {
for (int i = 0; i < column.View.RowCount; i++)
column.View.SelectCell(i, column);
}
If your grid view is editable, cell editors might steal the MouseDown event. In this case, you'll need to reconfigure the grid as described in this discussion: GridView - How to catch a cell click?
I need to delete the whole column in a DataGridView based on a certain condition. My DataGridView columns consists of numbers (1,2 and 3) the condition would be to delete all columns that does not contain (1,2 and 3). For Example if the column has only (1 and 3) it should be deleted.
How do I Overcome this? as many threads I went through only cover when you are certain of an index like below.
myGridView.columns.RemoveAt(index);
Some suggest hiding columns and thats not what I want, I want to completely remove the column from the DataGridView.
While it's better to do the job using data source of the DataGridView, but if the control is not bound to a data source, you can also use linq to get values from columns and check for some criteria, for example:
dgv1.Columns.Cast<DataGridViewColumn>()
.ToList().ForEach(c =>
{
var values = dgv1.Rows.Cast<DataGridViewRow>().Where(r => !r.IsNewRow)
.Select(r=>r.Cells[c.Index].Value).ToList();
if (!values.Contains(1)) //your custom criteria
dgv1.Columns.Remove(c);
});
Here is a really simple test. Load dgv1 this way:
dgv1.ColumnCount = 2;
dgv1.Rows.Add(1, 2);
dgv1.Rows.Add(3, 4);
Then use above code to delete columns and it just removes the last column.
I have these members on my DataGridView.
private DataTable _dataTable = new DataTable();
public DataTable DataTable {
get { return _dataTable; }
set {
_dataTable = value;
int rowIndex = -1;
//want to preserve the location where the datagridview is scrolled to
if (this.Rows.Count > 0) rowIndex = this.FirstDisplayedScrollingRowIndex;
this.DataSource = new BindingSource() { DataSource = _dataTable };
//-1 is out of bounds and the datasource could have been set
//to a smaller amount of rows after the rowIndex was set
if (rowIndex > -1 && rowIndex < _dataTable.Rows.Count) this.FirstDisplayedScrollingRowIndex = rowIndex;
}
}
When rows are added, removed or edited they are done so in _dataTable. When the rows are changed, DataTable is set so that the DataGridView displays the changes by binding the data to it. My problem is when the DataGridView is sorted by clicking one of the column headers. This changes the display of the DataGridView, but not the order of the rows in the underlying DataTable. How can I get it so _dataTable is sorted like the DataGridView?
I have considered adding a column to keep track of row indexes, but it seems like there should be another way and I don't really want to add a column since this is an abstract class. I have tried handling it in the DataGridView.Sorted events but haven't come up with any solutions that would work.
There is no way to transfer the sorting of the view into the table - not any that are provided by the DataGridView or DataTable classes. Why would you want to? If you are sorting based on a column, that column is in the table, and will be in the table any time you want to iterate through or sort the table in the order of that column.
If you want to persist the user's choice of sort column for the view, that is a different kettle than trying to save the specific sort position for each row. I would recommend just saving what column the user chose. This would not belong in that same table, but in a separate settings storage. If you absolutely want to store the sort position of each row, then you do need a separate column that has the sort order for each row, and you will need to capture the header mouse click event and repopulate that column appropriately.
Also, the minute you add a sort-order column to that table, that is dependent on what column the user chose to sort the data, you de-normalize the data. This means you will run into problems of maintaining data integrity - you will have to capture all sort of events and re-update that column... for example, what if the user changes the value for a row in the middle of the table, such that it now belongs at the end... update the value of that sort order column for that row and every row between its old and new position. What if the user deletes a row - update the value of the sort order column for all rows between the deleted row and the last row of the table.... and on and on with all sorts of user operations.
Much better, store the column name in a setting, and whenever the table is loaded into the gridview, tell the gridview to sort on the column stored in that setting. I am not sure if I am being clear - sorry.
Well explained on msdn. You have to set Columns SortMode and the direction ascending/descending.
I have a question. Let's say i have a checkboxlist with the ingredieints for a cake and i choose not just one but more ingredients (3-4). I want to save this in datagridview. Can datagridview show more than one ingredient or is this not possible ?
You see i'm making an application for bakeries and for ordering cakes you will choose the type of cake and adding(toppings) and the number of cakes you want. Then I would like to save this to datagridview, or show this in dgv and then when I would finish with ordering i would just click on send button in dgv and all the orders i made would be sent to an email. I hope you understand what i want.
Even in its simplest uses a DataGridView is a 2-dimesional container; a 'grid', so you can have as many rows and columns as you want.
If you want to display them all in row you should first try to estimate the maximum number of ingredients. Then you add this number of columns to the target DGV.
Then add a row and fill its column cells with the ingredients.
In case you come across a cake with even more ingredients that would't be a problem either as you can always add more columns.
Empty cells are no problem, just make sure to always check for null values.
By the way, cells are quite powerful and you can have a tag for each single cell, so you can add as many data of any complexity to the cell beyond its mere value!
Here is some simple sample code:
while (dataGridView1.ColumnCount < checkedListBox1.CheckedItems.Count)
dataGridView1.Columns.Add("", "");
int newRow = dataGridView1.Rows.Add();
int item = 0;
foreach ( object o in checkedListBox1.CheckedItems)
{
dataGridView1[item, newRow].Value = o.ToString();
item ++;
}