DataGridView ID Column Will Not Hide - c#

I have a DataGridView bound to an ObjectDataSource some of the columns are hidden including the ID column. The problem is that the ID column shows up even when its visible property is set to false. Has anyone run into this problem before? Setting the width to zero is not an option since the grid doesn't allow columns with a width less than 5 pixels wide so it still shows the column on the grid no matter what.
The strange thing is that the ID column wasn't always showing. After I worked on the app for a bit the columns appeared again.
DataGridView is not set to auto generate columns. I am building to version 4.0 of .NET and C#.
Here is the code in the form constructor.
dgvActiveMiners.AutoGenerateColumns = false;
dgvAvilableMiners.AutoGenerateColumns = false;
dgvOperationResults.AutoGenerateColumns = false;
dgvActiveMiners.Columns["dgvActiveMinersRecordId"].Visible = false;
dgvAvilableMiners.Columns["dgvAvilableMinersRecordId"].Visible = false;
dgvOperationResults.Columns["dgvOperationResultRecordId"].Visible = false;
This is the generated code for the grids.
this.dgvOperationResults.AllowUserToAddRows = false;
this.dgvOperationResults.AllowUserToDeleteRows = false;
this.dgvOperationResults.AutoGenerateColumns = false;
this.dgvOperationResults.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this.dgvOperationResults.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
this.dgvOperationResultRecordId,
this.nameDataGridViewTextBoxColumn2,
this.typeIdDataGridViewTextBoxColumn,
this.amountDataGridViewTextBoxColumn,
this.operationIdDataGridViewTextBoxColumn});
this.dgvOperationResults.DataSource = this.operationResultBindingSource;
this.dgvOperationResults.Location = new System.Drawing.Point(12, 40);
this.dgvOperationResults.MultiSelect = false;
this.dgvOperationResults.Name = "dgvOperationResults";
this.dgvOperationResults.ReadOnly = true;
this.dgvOperationResults.Size = new System.Drawing.Size(498, 247);
this.dgvOperationResults.TabIndex = 16;
I don't know what else I could be missing?
Thanks!

Suggestion 1:
Try explicitly setting the DGV Column's Visible property to false in the FormLoad event:
dataGridView.Columns["YourIdColumn"].Visible = false;
Suggestion 2:
Try changing your column dgvActiveMinersRecordId from the first column in the DGV to the last column.

To try and answer this a bit more generically for the next person who comes along, like me...
This does seem to be a bug, but the work around is to:
Make sure the columns you want to hide are displayed last
This will depend on your code, but for some this will be:
SQL code changed to return the columns later
Change the code that adds the datagridview columns putting the "to hide" columns at the end
Setting the Columns[x].DisplayIndex such that the columns appear last, as per #Steve's post

I have the same issue.
The following line, still leaves the column visible, even though exploring the value shows it false.
dataSelected.Columns["id"].Visible = false;
I didn't have this issue, until I had set the DisplayIndex on a column
dataSelected.Columns["ipagenum"].DisplayIndex = 6;
Moving the offending columns DisplayIndex to the end, corrected this issue.
dataSelected.Columns["id"].DisplayIndex = 15;

Maybe a bit late but I was beating myself up with the same problem, I had two separate forms with DataGridViews both bound to different DataTables. One had no problem hiding the 1st column, on the other everything I tried didn't work, until...
Note: ["newCol"] is the first (i.e. column 0) column in the data table.
This code Fails to hide column [0] (or by name ["NewRow"])
...
MyDataGridView.DataSource = MyDatatable;
MyDataGridView.Columns["NewRow"].Visible = false; // doesn't hide (col 0)
// MyDataGridView.Columns[0].Visible = false; <<<< this didn't work either
MyDataGridView.Columns["Changed"].Visible = false;
MyDataGridView.Columns["Active"].Visible = false;
MyDatatable.RowFilter = "[Active] = 1";
...
this code works:
...
MyDataGridView.DataSource = MyDatatable;
MyDatatable.RowFilter = "[Active] = 1";
MyDataGridView.Columns["NewRow"].Visible = false; // YAY!! Now it hides
// MyDataGridView.Columns[0].Visible = false; <<<< and this works too
MyDataGridView.Columns["Changed"].Visible = false;
MyDataGridView.Columns["Active"].Visible = false;
...
Spot the difference? It's Where I specify the RowFilter.
The other form doesn't have a starting RowFilter but in both forms I later change the RowFilter (depending on user actions), column 0 never comes back.
Seems specifying RowFilter too soon after hiding columns fails for column 0.
Very very weird!!!! Very very frustrating!!!!

That's odd.
Are you certain you are calling the right column name? I realize that would be a stupid mistake to make, but it happens!
Here's a simple test you could try:
void test(string columnName, bool visibility) {
if (dataGridView1.Columns.Contains(columnName)) {
dataGridView1.Columns[columnName].Visible = visibility;
} else {
throw new Exception(string.Format("Column '{0}' does not exist in DataGridView '{1}'.", columnName, dataGridView1.Name));
}
}

I would like to contribute a perspective that has not been mentioned.
Each column of the DataGridView has a property name. You can directly access the column by name, as you would to access any other element. For example: ColumnName.Property = AnyProperty. In your case: ColumnName.Visible = false.
I think it is cleaner, more direct, and less likely to make a mistake. We also help a bit the compiler :)
In this way, it is not necessary to use the property name of the DataGridView, neither locate the desired column mediate a string (which potentially can be commited
an error). I mean this: YourDataGridView.Columns ["YourColumn"] Property = AnyProperty.

I had the same issue and none of the above worked for me. My fix was to set a DataPropertyName at least for the column that should be hidden in the designer at "Edit columns".

If you want to hide a column by name, you have to give a Name at your column. Initiliaze the property Name and after you can use it by code.

I was having the same problem, and I did not want have to change the index of my id column to the visible property works. So I noticed that after I indicated that the id column visible = false, I was deleting the last row of the DataGridView and this is what was making the id column appear. So I delete the row first and then indicate that the id column = false.

I have a similar problem. I added an unbound checkbox column to my data bound grid. It became the first column.
When I stepped through my grid like so:
for (int i = 0; i < grvQuoteCostSheets.RowCount; i++)
{
grvQuoteCostSheets[grcQCostSProfit.Index, i].Value
= (Convert.ToInt32(grvQuoteCostSheets[grcQCostSPrice.Index, i].Value) - Convert.ToInt32(grvQuoteCostSheets[grcQCostSTotalCost.Index, i].Value));
}
idColumn.Visible = false; //Need to rehide.
The first hidden column visibility switched to False. I moved the CKBox column from first to 3rd place as suggested in a different answer (the next two columns being an ID value & Line# respectively, and hidden) and the checkbox column stayed hidden. I was hiding the ID column after the math as it was flipping to Visible. I just lived with it before (hiding the ID column after the math loop), but now that I added the checkbox column, I decided to dig a bit, and here I am.
I also tried doing the math in a list grabbed from the grid, and the checkbox column would still flip to Visible when the CKBox was first. I’m still stuck with the first hidden column wanting to flip to visible, so I re-hide it.
I do have AutoGenerateColumns = False and am explicitly setting the first column visibility to false as well. Both to no avail.

Don't know if anybody is still struggling with the issue.
I had the same problem and was setting the visible property in the dataSourceChanged event.
When I put the visible false in the show event instead it worked.

Related

problems with autowidth for columns of a grid control from devexpress

I'am using a grid control from devexpress in a desktop application(C#).
I set a datasource and then I export to Excel.I want that all my columns take the width of longest row value from that column.
In this grid I use different datasources .
In load form I set :
gvExport.OptionsPrint.AutoWidth = false;
gvExport.BestFitColumns();
grdExport.DataSource = ds;
XlsExportOptions vOptions = new XlsExportOptions();
vOptions.TextExportMode = TextExportMode.Text;
vOptions.ShowGridLines = true;
vOptions.SheetName = "Test";
prmFileName = "Test.xls";
grdExport.ExportToXls(prmFileName, vOptions);
My ds can be a list or a dataTable.
1.Can somebody hepl me to autosize the lenght of columns?
2.How can I set to ladscape the Excel page that I generated?
Thanks
For the first part of the question you can use
GridView.OptionsView.ColumnAutoWidth = true
if you want to set the width according to a particular column, let say the first column you have to inheret the GridView and then override the functions BestFitColumn and OnColumnWidthChanged.
For the second part you have to use the printing system like this:
PrintableComponentLink link = new PrintableComponentLink(new PrintingSystem());
link.PaperKind = System.Drawing.Printing.PaperKind.A4;
link.Component = myGridControl;
link.Landscape = true;
and then use an ExportOption, here an example of Xls:
XlsExportOptions _Options1 = new XlsExportOptions();
_Options1.SheetName = fileName;
_Options1.ExportMode = XlsExportMode.SingleFile;
link.ExportToXls(sfd.FileName, _Options1);
Note for others there is XlsxExportOptions, PdfExportOptions,RtfExportOptions ...etc
Tou should know that the BestFitColumns() method iterates on the rows of the data source to compute the best width for the columns.
So, you have to put it AFTER setting your data source.
Therefore, I recommend you not to use this method and set manually the width of the columns instead. In fact, the BestFitColumns() method slows considerably the loading of your grid (if you are dealing with >1k rows).
For Exporting to a landscape mode, you'd probably find an answer here.

How do I select a column in data grid view? [duplicate]

I've been trying to find out how to select all cells under a Column with a 'mouse right click+menu+Select this Column'...
MSDN isn't helping much...
I get this error when I try to change selection mode:
DataGridView control's SelectionMode cannot be set to FullColumnSelect while it has a column with SortMode set to DataGridViewColumnSortMode.Automatic.
Thanks,
Y_Y
Sorry it took so long - I wanted to test before I answered, so I plopped this into Visual Studio to test first.
I had to do this in mine to get it to work:
foreach (DataGridViewColumn c in dataGridView1.Columns)
{
c.SortMode = DataGridViewColumnSortMode.NotSortable;
c.Selected = false;
}
dataGridView1.SelectionMode = DataGridViewSelectionMode.FullColumnSelect;
dataGridView1.Columns[0].Selected = true;
Loop through the cells in the column and set their Selected property to true.
It sounds horrible, but I believe it's the only way to select an entire column and keep automatic sorting.
For example:
grid.ClearSelection();
for(int r = 0; r < grid.RowCount; r++)
grid[columnIndex, r].Selected = true;
You need 3 things.
Clear all selected rows and cells.
Remove the sort mode of every column to Not sortable. The default click event is sort, now it will be select.
Set the selection mode to column.
Finally you can select the first column to show user the selection mode.
This only have to be done once. The first time you load your form or your datagridview.
// Clear all selected cells or rows in the DGV.
dataGridView1.ClearSelection();
// Make every column not sortable.
for (int i=0; i < dataGridView1.Columns.Count; i++)
dataGridView1.Columns[i].SortMode = DataGridViewColumnSortMode.NotSortable;
// Set selection mode to Column.
dataGridView1.SelectionMode = DataGridViewSelectionMode.FullColumnSelect;
// In case you want the first column selected.
if (dataGridView1.Columns.Count > 0 ) // Check if you have at least one column.
dataGridView1.Columns[0].Selected = true;
I got this error while starting with WPF using the drag and drop interface and none of the manual coding. Viewing the properties of datagrid would give a way to select items like this:
But trying to change to type to Column Header Select or Column Select would result in the error you mentioned.
So how it was solved was by right-clicking on the grid and go to Edit Columns. Here all the columns and their SortingMode is available to change. Change them all to NotSortable.
I know this is a very old question. But I leave my solution below for people who will encounter this error in the future.
You will get this error through properties(UI) in general.
I mean when you do SelectionMode -> FullColumnSelect or ColumnHeaderSelect. You get it. For this reason, I suggest you to change the SelectionMode via code instead of UI.
My solution is as follows.
Give your data to DataGridView as SelectionMode.FullRowSelect or SelectionMode.RowHeaderSelect.
Make all columns not sortable in a loop.
Change the dataGridView's selection mode in code.
//1
dataGridView.DataSource = productList;
//2
for (int i = 0; i < dataGridView.Columns.Count; ++i)
dataGridView.Columns[i].SortMode = DataGridViewColumnSortMode.NotSortable;
//3
dataGridView.SelectionMode = DataGridViewSelectionMode.FullColumnSelect;

How to disable Null image in DataGridView image column when populated from DataTable

I have an existing application with a new requirement to show an image in a DataGridView cell to denote whether the record has a specific flag associated with it or not (not user editable, this comes from the DB).
If there is a flag, I show the corresponding image, and if there's no flag, I want nothing to be shown in the column.
The DataGridView columns weren't created in Visual Studio designer, or else this would easy. I could just set the NullValue property on the column. Instead the columns are created at runtime when all the data is loaded into a DataTable, and then a DataView is created from that DataTable, and then the DataGridView's Datasource is set to the DataView.
I can't completely rewrite this, or else I'd just define the columns in VS Designer instead of this ridiculous way of just letting the columns be defined from the DataTable.
My question is then, how can I make it so the column with the Images shows nothing when the underlying data table has a null?
Here's some pseudo C# to demonstrate what I mean. Remember, I didn't write it to use two DataTables like this; it was that way when I had it handed to me, and I don't want to make drastic changes just to add a new column...
DataTable rawData = someMethodThatReturnsMyRawData();
DataTable data = new DataTable();
data.Columns.Add("Flags", typeof(Image));
data.Columns.Add("SomeOtherColumn");
foreach (DataRow rawDataRow in rawData.Rows)
{
DataRow dataRow = data.NewRow();
bool hasFlagType1 = false;
bool hasFlagType2 = false;
if (rawDataRow["FlagType1ID"] != DBNull.Value)
{
hasFlagType1 = true;
}
if (rawDataRow["FlagType2ID"] != DBNull.Value)
{
hasFlagType2 = true;
}
if (hasFlagType1 && hasFlagType2)
{
dataRow[0] = Properties.Resources.BothFlagsImage;
}
else if (hasFlagType1)
{
dataRow[0] = Properties.Resources.FlagType1Image;
}
else if (hasFlagType2)
{
dataRow[0] = Properties.Resources.FlagType2Image;
}
else
{
//If neither flag set, I don't want it to show anything,
//but if I leave it as null, a little box with an X in it shows up
//I could set it to some transparent GIF here, but that seems lame
}
dataRow[1] = rawDataRow["SomeOtherColumn"];
data.Rows.Add(dataRow);
}
DataView dv = new DataView(data, string.Empty, "SomeOtherColumn ASC", DataViewRowState.CurrentRows);
this.emptyDataGridViewFromDesigner.DataSource = dv;
// How can I modify the column "Flags" at this point to show nothing if the value is null?
EDIT: Here's a screenshot so you can see what I mean by the little box with an X - those are all nulls...
Also, it has to be .NET 3.5, so if there's a solution in .NET 4.0 only, I'm out of luck.
I figured this out...
Have to cast the column as a DataGridViewImageColumn, then set the DefaultCellStyle.NullValue for that column to null. From my example above, you'd do it like this...
((DataGridViewImageColumn)this.emptyDataGridViewFromDesigner.Columns["Flags"]).DefaultCellStyle.NullValue = null;
I guess I jumped the gun asking here, but hope this helps someone else sometime.
It's FAR easier to simply assign new Bitmap(1,1); to the cell's .Value property and move on. My app was throwing exceptions whenever I tried to assign NULL to the Cell's Value, even with the modified DefaultCellStyle.NullValue
Something like this works as intended, every time, without any hassles or arcane/obscure settings:
dataGridView1.Rows[index].Cells["CellName"].Value = isFlag ? Properties.Resources.FlagImage : new Bitmap(1,1);
To fix whole grid, just add this code to Form constructor. (and change name of your dataGrid):
Load += delegate
{
// remove default [x] image for data DataGridViewImageColumn columns
foreach (var column in dataGridView1.Columns)
{
if (column is DataGridViewImageColumn)
(column as DataGridViewImageColumn).DefaultCellStyle.NullValue = null;
}
};

C# DataGridView Adding a Row - When validating, how do I know the row is new and not yet committed?

I have a client having a problem with a DataGridView in a Windows app. They are calling the CellValidated event, but they want to have different validation for the cell if it is in a row that is already committed back to the datasource than if it is a row that is first being added (and not yet committed (the user hasn't left the row yet). I tried the IsNewRow property, but as soon as you start typing in the row, another "new row" is added, so the row you are working with is no longer considered the new row. I know the row has not been committed yet because you can hit Esc to cancel editing, and the entire row goes away.
Is there a way to tell if the currently edited row is actually the "new row" in the sense that it hasn't been committed back to the datasource?
One way I've achieved something similar in the past is to utilise the id property of my objects that are bound to the list.
For example, if I have a BindingList<User> where user is something like:
public class Names
{
public string Name { get; set; }
public int id { get; set; }
}
I can then bind my list like this:
dataGridView1.AutoGenerateColumns = false;
_users = new BindingList<User>();
_users .Add(new Names() { Name = "joe", id=1 });
_users .Add(new Names() { Name = "pete", id = 2 });
bindingSource1.DataSource = _names;
DataGridViewTextBoxColumn col1 = new DataGridViewTextBoxColumn();
col1.DataPropertyName = "Name";
dataGridView1.Columns.Add(col1);
dataGridView1.DataSource = _users;
Then, when the DataGridView provides a new row, it will have an id of 0 (the default value for an integer).
Every object that comes from the database has a non zero id.
There may also be a way to achieve this using BindingSources but I had a quick look over the properties there and nothing leaped out at me.
What is the data source in this case?
If it's a datatable, then you can easily test the DataRowState property of the datatable's rows to see if they are new or existing.
Once you've validated your datarows, you can then call an Accept on the table to commit those rows.
There is no need to interfere between the grid and it's datatable, in this situation.
Of course, this doesn't mean your data is actually committed to a database, if that's where it's finally stored. That would be another step.
Also, I usually avoid directly writing to a datagridview; instead, I make it read-only and pop up an add/entry screen which can perform any validation required.
I don't know if any of this has been of use to you - if I've missed the point please let me know.
This should help people that aren't using DataTable objects:
In the CellBeginEdit event set the Tag property to some value that you will use to differentiate the 'new' row
private void dataGridView1_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
{
if (e.RowIndex == dataGridView1.NewRowIndex)
dataGridView1.Rows[e.RowIndex].Tag = true;
}
Then in your validating event you can check for that value:
if (dataGridView1.Rows[e.RowIndex].Tag is bool
&& (bool) dataGridView1.Rows[e.RowIndex].Tag)
{
// new row code
// after it's added, mark it as 'not new'
dataGridView1.Rows[e.RowIndex].Tag = false;
}
else
{
// existing row code
}
GenericMeatUnit's answer didn't work for me, but it provided me with enough to find a way to make it work. Here's how I am doing the check now:
if (this.DATASET.DATATABLE.Rows.Count == e.RowIndex)
This if statement works because before leaving the row in the DataGridView, it doesn't actually exist in the datatable yet, so the number of rows in the datatable will be equal to the RowIndex for the new row, since RowIndex is zero-based.

C# WinForms DataGridView - Constant Row Selected!

I have a winforms datagridview that seems to always have at least one row selected all the time. I'm not interested in being able to select the rows at all really, I just need the user to be able to select the checkbox in column 1.
Any ideas why there is always at least 1 row selected?
How can i prevent this?
Will it affect the ability to select the checkbox in column1?
Below are my Datagridview settings:
this.dataGridView1.AllowUserToAddRows = false;
this.dataGridView1.DefaultCellStyle.WrapMode = DataGridViewTriState.True;
this.dataGridView1.DefaultCellStyle.ForeColor = Color.Black;
this.dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
this.dataGridView1.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.AllCells;
this.dataGridView1.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
this.dataGridView1.MultiSelect = false;
this.dataGridView1.RowHeadersVisible = false;
this.dataGridView1.RowsDefaultCellStyle.BackColor = Color.WhiteSmoke;
this.dataGridView1.AlternatingRowsDefaultCellStyle.BackColor = Color.LightGray;
this.dataGridView1.ColumnCount = 0;
colSelect = new DataGridViewCheckBoxColumn();
colSelect.HeaderText = "Select Message";
colSelect.Width = 90;
this.dataGridView1.Columns.Insert(0, colSelect);
this.dataGridView1.Columns[0].DataPropertyName = "msgSelect";
Goober, I encountered a similar problem, where I needed user to select rows using checkboxes. The first row is always selected by default after the gridview is populated irrespective of the gridview settings. To make sure the first row is not selected, everytime the gridview is populated, do a ClearSelection():
this.dgridvw.DataSource = this.MyTable;
this.dgridvw.ClearSelection();
ClearSelection() clears all the selected rows.
You should use DataGridView.ClearSelection() to remove any selection(s) after you have populated your DataGridView.
Also you can make specific columns read only allow which would allow to restrict editing to your checkbox column only. See DataGridViewColumn.ReadOnly Property
Make sure your are NOT calling the method to load the data from the form constructor. If you call it from the form.load()
also after the datagridview is loaded do this
DataGridView.Rows[0].Selected = false;
Select the datagridview. Then, in the properties window scroll down until you find the property SelectionMode and change it to FullColumnSelect.
Alternatively if you want them to just select one checkbox at a time change it to CellSelect

Categories