There is a datagridview table, c# language.
Consisting, for example, of 6 columns. It is necessary to add the seventh, but not to the end of the table, but to the third place.
But because of this, you will have to rewrite a lot of code, because the column indexes will shift.
I'm interested in the question: is it possible to visually display a column in the third position, and refer to it as 7?*
*I understand that indexes start from zero and will be 2 and 6 respectively.
Screens:
Table columns
Visual display
Your question is: Is it possible to visually display a column in the third position, and refer to it as 7? and the answer is yes.
As a suggestion, what works best for me is to not deal with the int index at all, but to use the string indexer of Datagridview.Columns and use datagridview.Columns["columnName"] to refer to individual columns. This solves the problem of having to rewrite code when the index changes from an insert (as you mentioned) because you refer to columns by name.
Sometimes you know what all the possible column names might be. In this case, you can make this even more robust by abstracting them out to an enum:
enum StdColumnName
{
Apple0,
Orange1,
Banana2,
}
Example GitHub
Override this method in MainForm:
protected override void OnHandleCreated(EventArgs e)
{
base.OnHandleCreated(e);
foreach (string name in Enum.GetNames(typeof(StdColumnName)))
{
var col = new DataGridViewTextBoxColumn()
{
Name = name,
HeaderText = name,
AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill
};
dataGridView.Columns.Add(col);
}
}
to get this:
then click the button:
private void btnChangeOrder_Click(object sender, EventArgs e)
{
var col = dataGridView.Columns[nameof(StdColumnName.Banana2)];
col.DisplayIndex = 0;
Debug.WriteLine(
$"The Banana2.Index is { dataGridView.Columns[nameof(StdColumnName.Banana2)].Index}");
Debug.WriteLine(
$"but Banana2.DisplayIndex is { dataGridView.Columns[nameof(StdColumnName.Banana2)].DisplayIndex}");
}
to get this:
Now col.Index and col.DisplayIndex are two different numbers but using the name still works.
Hope this give you a few ideas.
Related
I have a User Control with an Ultragrid. In a particular form where I add a ValueList. The value list will not show for the particular column I'm interested in. If I then code in another column instead by changing the index value for columns I get the value list in the column.
The code looks like:
private void AddCombo(object sender, UcUltraGen.RowClickArgs e)
{
ValueList vl;
if (!ucUltraGridMain.Grid.DisplayLayout.ValueLists.Exists("Texas"))
{
vl = ucUltraGridMain.Grid.DisplayLayout.ValueLists.Add("Texas");
}
else
{
vl = ucUltraGridMain.Grid.DisplayLayout.ValueLists["Texas"];
}
var row = e.VariantRow;
List<PcBase> list = PcBase.PcBaseList.Where(x => x.VariantId == row.Cells["Id"].Text).ToList();
AddValueList(list, vl);
ucUltraGridMain.Grid.DisplayLayout.Bands[0].Columns[1].ValueList =
ucUltraGridMain.Grid.DisplayLayout.ValueLists["Texas"];
And if I change to
...
ucUltraGridMain.Grid.DisplayLayout.Bands[0].Columns[2]
It works. How can I have changed the behavior of columns[1]?
The property in column[1] was read only that is it only had a "get" implemented. By adding a set it worked. Hope this helps someone.
There are different methods to get the index of a datagridview column in C#, for example:
dataGridViewTextBoxColumn1.Index;
dataGridViewTextBoxColumn1.DisplayIndex;
datagridview1.Columns[column.name].Index;
datagridview1.Columns[column.name].DisplayIndex;
The dataGridViewTextBoxColumn1 is inside the DataGridViewColumnsCollection List.
Desingner Code:
this.datagridview1.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
this.dataGridViewTextBoxColumn1,
this.dataGridViewTextBoxColumn2,
this.dataGridViewTextBoxColumn3
}
I was experiencing the different methods, but in strange cases I obtain differents values, for example I use this:
datagridview1.Columns[dataGridViewTextBoxColumn1.name].Index;
I get the real index relative to the column collection, in my test the value is 3.
but if I use this:
dataGridViewTextBoxColumn1.Index;
I get a distinct index, in my test the value is 1.
I do not understand that, because in theory is the same property, doesn't it?,
in case of the displayindex property the result is similar. In my datagridview I have invisible and read only columns.
In other tests, I get the correct values for all cases, and this datagridivew contains more visible and invisible columns to.
My question is: what is the best method for get the correct index of the column in a DataGridView, if I use the events, for example CellContentClick to equalize the DataGridViewCellEventArgs.ColumnIndex?
example:
private void datagridview1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
if (e.RowIndex >= 0 && e.ColumnIndex.Equals(datagridview1.Columns[dataGridViewTextBoxColumn1.Name].Index))
datagridview1.Rows[e.RowIndex].Cells[dataGridViewTextBoxColumn2.Index].Value = true;
}
UPDATE
this is my test is a visual studio watch:
TEST 1:
private void dgvTerminales_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
if (e.RowIndex >= 0 && e.ColumnIndex.Equals(dgvTerminales.Columns[clmActiva.Name].Index))
dgvTerminales.Rows[e.RowIndex].Cells[clmEditado.Index].Value = true;
}
TEST 2:
Other datagridview with same properties, columns and form.
private void dgvSucursales_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
if (e.RowIndex >= 0 && e.ColumnIndex.Equals(dgvSucursales.Columns[clmActiva.Name].Index))
dgvSucursales.Rows[e.RowIndex].Cells[0].Value = true;
}
clmActiva is a DataGridViewCheckBoxColumn column type.
Update # I lost count
Index
Gets the relative position of the band within the DataGridView control.
The value of this property does not necessarily correspond to the current visual position of the band within the collection. For example, if the user reorders columns in a DataGridView at run time (assuming the AllowUserToOrderColumns property is set to true), the value of the Index property of each column will not change. Instead, the column DisplayIndex values change. Sorting rows, however, does change their Index values.
DisplayIndex
Gets or sets the display order of the column relative to the currently displayed columns.
Unlike the Index property, the DisplayIndex property corresponds to the current position of the column as displayed by the user interface (UI). By default, each column's DisplayIndex is set to numbers of increasing order, which reflects the order in which they were added. The Visible property value does not affect the DisplayIndex value.
Update
Ok so it seems the OP left out his exact code which makes this next to impossible to help but after all of the comments in this thread, here goes my next set of results.
The OP is using a DataGridViewCheckBoxColumn so in fact by using CellContentClick this is not incorrect. Changing the CheckBox value will properly fire this event.
The order of events fired would follow CellClick, CellContentClick
Now that this is out of the way, Next
Without having your exact code and trying to piece it together I have the following. (Note because I change these names in the designer, if you try to edit it in the UI it causes issues but I was matching what OP provided so as long as these are adjust in designer.cs itself it works fine lol. The visual designer will yell at you trying to use these names)
this.dataGridViewTextBoxColumn1 = new System.Windows.Forms.DataGridViewCheckBoxColumn();
this.dataGridViewTextBoxColumn2 = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.dataGridViewTextBoxColumn3 = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.dataGridView1.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
this.dataGridViewCheckBoxColumn1,
this.dataGridViewTextBoxColumn2,
this.dataGridViewTextBoxColumn3});
So my DataGridView has 1 CheckBox and 2 Text Columns
below registers all values as 0 when I click the first column with the checkbox which is correct. The event will not fire on TextBox columns.
private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
int a = e.ColumnIndex;
int b = dataGridView1.Columns[dataGridViewCheckBoxColumn1.Name].Index;
int c = dataGridViewCheckBoxColumn1.Index;
if (e.RowIndex >= 0 && e.ColumnIndex.Equals(dataGridView1.Columns[dataGridViewCheckBoxColumn1.Name].Index))
dataGridView1.Rows[e.RowIndex].Cells[dataGridViewTextBoxColumn2.Index].Value = true;
}
When I change the position of the CheckBox to be the second column in the grid rather than the first. Then the above values register as all 1 which is correct again.
I don't see any issues. Please again provide us with your exact code, controls ...etc. There is still something missing we can't see as there isn't an issue with what you are providing.
Clearly (if you are getting different results),
column.Index;
Is not pointing to the same instance as:
datagridview1.Columns[column.name].Index;
To prove it display the .GetHashCode() value of both.
I'm currently trying to add data programatically onto a DataGridView, but it doesn't seem to be working.
What I have is an Array, which I fill from a text file:
public static string PathList = #"C:\Users\gbbb\Desktop\Pfade.txt";
_PathRows = System.IO.File.ReadAllLines(#PathList);
and I have a DataGridView with 4 Columns on which I add as many Rows as I have paths, so:
public void InitPathsTable()
{
TabelleBib.Rows.Add(_PathRows.Length);
//And here is where i want to add the Paths on Column Nr.4
}
Next what I need is a way to add all paths that I get (24) into the Column Nr.4,
one Path per Row.
But it seems to be nearly impossible for a beginner like me, so I am asking you.
This is method that will do that for you. Read comments (especially make sure you have added 4 columns to you DataGridView):
public void InitPathsTable()
{
int rowindex;
DataGridViewRow row;
foreach (var line in _PathRows)
{
rowindex = TabelleBib.Rows.Add(); //retrieve row index of newly added row
row = TabelleBib.Rows[rowindex]; //reference to new row
row.Cells[3].Value = line; //set value of 4th column to line. WARNING: TabelleBib has to have 4 columns added either from code or designer othwerwise here you will get exception
}
}
if you get any more problems, write a comment and I will come back to you :)
I have a datatable bound to a datagridview. However, the ordering of columns is messed up. I already made a column headers for each field put dataproperty name. I arranged it in the designer view. However, if i run the program column headers doesn't follow my arrangement. =_=. Does anybody know how to solve this....
EDIT::
I've Tried this approach. Is it Okay?
void SortDataGridViewColumns(DataGridView dgv)
{
var list = from DataGridViewColumn c in dgv.Columns
orderby c.Index
select c;
int i = 0;
foreach (DataGridViewColumn c in list)
{
c.DisplayIndex = i++;
}
}
***I've got this here but I use Index instead of Headertext. CASE CLOSED! LOL
I think you wil need to change the column order in runtime.
From MSDN:
When you use a DataGridView to display data from a data source, the columns in the data source's schema sometimes do not appear in the order you would like to display them. You can change the displayed order of the columns by using the DisplayIndex property of the DataGridViewColumn class.
You can change the order of the columns like this:
private void AdjustColumnOrder()
{
customersDataGridView.Columns["CustomerID"].Visible = false;
customersDataGridView.Columns["ContactName"].DisplayIndex = 0;
customersDataGridView.Columns["ContactTitle"].DisplayIndex = 1;
customersDataGridView.Columns["City"].DisplayIndex = 2;
customersDataGridView.Columns["Country"].DisplayIndex = 3;
customersDataGridView.Columns["CompanyName"].DisplayIndex = 4;
}
http://msdn.microsoft.com/en-us/library/wkfe535h.aspx#Y0
If you're going t use it frequently, I recomend you to make use of extension methods to add sintactic sugar and make it easy to read and maintain.
how Select the row index in datagrid ?
The event SelectionChanged
The following code does not work :
private DataGridRow dgr = new DataGridRow();
private void dataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
this.dgr = this.dataGrid.ItemContainerGenerator.ContainerFromItem(this.dataGrid.SelectedItem) as DataGridRow;
MessageBox.Show(this.dgr.GetIndex().ToString());
}
The reason why above code would not work is because wpf data grid is virtualized and it may not return the row using the itemContainerGenerator.ContainerFromItem because it may be lying outside the scroll view.
For this you will have to use the datagrid's items collection and the IndexOf call using selected item.
private void dataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var dg = sender as DataGrid;
MessageBox.Show(dg.Items.IndexOf(dg.SelectedItem).ToString());
}
My answer is late, but I hope it still will be useful for people who found this post from search engines. This is more general solution which also helps to define indexes of all the selected rows.
List<int> RowIndexes = new List<int>();
int SelectedItemsCount = yourDataGrid.SelectedItems.Count;
for (int i = 0; i < SelectedItemsCount ; i++)
{
RowIndexes.Add(yourDataGrid.Items.IndexOf(yourDataGrid.SelectedItems[i]));
}
And now RowIndexes contains all indexes of the selected rows. Just put the code inside the event you wish, that's all.
This is a late answer, but this is how I accomplished it. This gives you index of every selected row in the DataGrid (dgQuery is the name of my DataGrid):
foreach (var selection in dgQuery.SelectedItems)
{
DataRowView row = (DataRowView)item;
int index = Convert.ToInt32(row.Row[0]) - 1;
}
It gives 1 at index 0, so we need to subtract 1 at every index.
.Row[0] Is actually a column (in my head)... of that DataRowView, not sure why it's called a row. You can change it to [1], [2] and so on to view other cells within that row.
With this solution, you don't need a collection, array, nothing of that sort. You just work with what's at hand and make use of existing code.
The huge plus side of this implementation, at least for me, was the fact that it goes through selected items in the order they were selected. This can be a very powerful tool if you wish to know the order of user's selection.
I'm posting this because I just spent over 4 hours looking for a solution. I even gave up on check boxes because I don't have enough time to implement those to work well... maybe down the road.