Seems to be a common issue.
I'm trying to hide a column of my GridView. I have read that simply setting the column to 'visible = false' will not work as I'm auto-generating my data.
Currently my code stands as so:
protected void Page_Load(object sender, EventArgs e)
{
bind();
if (GridView1.Columns.Count > 0)
GridView1.Columns[0].Visible = false;
else
{
GridView1.HeaderRow.Cells[0].Visible = false;
foreach (GridViewRow gvr in GridView1.Rows)
{
gvr.Cells[1].Visible = false;
}
}
}
The 'if' statement will not trigger as as said I am auto-generating the data. With the above loop, I can hide the header text of the column but want to hide the whole column with the ability to still be able to access the hidden data.
How about just doing this later in the control's life cycle (when the Columns collection has been populated):
protected void GridView1_PreRender(object sender, EventArgs e)
{
if (GridView1.Columns.Count > 0)
GridView1.Columns[0].Visible = false;
else
{
GridView1.HeaderRow.Cells[0].Visible = false;
foreach (GridViewRow gvr in GridView1.Rows)
{
gvr.Cells[1].Visible = false;
}
}
}
Note: you would need to add OnPreRender="GridView1_PreRender" to your GridView markup.
Why not use the GridView.DataKeyNames and GridView.DataKeys properties to store the ID and then retrieve it with the rowIndex later? This also will keep the column from being autogenerated.
DataKeyNames
DataKeys
This is a limitation with auto-generating columns. You give up a lot of control over HOW the columns are displayed for the convenience of not pre-defining them.
Bite the bullet now and define your columns. If this is the ONLY customization you need to make, you may be all right, but 90+% of the time I end up defining columns to customize how they are displayed.
Otherwise you're going to end up with several of these "tweaks" that are prone to breaking under various circumstances (e.g. the order of the columns changes in the data source).
Ah... so the problem is the Columns is not predefined.
Perhaps you could use Linq to select all the columns you want to display:
gvTest.DataSource = (from d in dataSource
select new
{
ColumnA = d.ColumnA...
}
Alternatively, you could hide the columns with JavaScript;
Related
I want to add value into a Grid view via dropdownlist with a button.
I want the ddTN.SelectedItem.value in the Grid view to be unique. No duplication
How do I check every row for the ddTN.SelectedItem.value before adding a new ddTN.SelectedItem.value into the Grid view?
This are the codes that I have and it keep comparing the value with the first value in the gridview. Not the others.
I don't want to use a checkbox and such. All the example I found required using checkbox.
protected void Insert(object sender, EventArgs e)
{
int i = 0;
var p = 1;
DataControlFieldCell cell = GridView1.Rows[i].Cells[p] as DataControlFieldCell;
if (cell.Text != ddTN.SelectedItem.Value)
{
dt.Rows.Add(ddTN.SelectedValue, ddDuration.SelectedValue);
ViewState["Customers"] = dt;
this.BindGrid();
label.Text = "";
p++;
}
else
{
label.Text = "Exercise already inserted";
}
}
It looks like you were intending on looping over the items in the grid but you have forgotten the looping mechanism. In your code, it always only checks the first item because i is initialized to 0 and never changes.
Try using a looping mechanism like a for loop or a while loop. Or, if you know the items in the grid from the beginning, perhaps use a hash table for quickly checking if the selected item already exists.
Keep trying, you are almost there!
I'm trying to figure out how to get a bounded datagridview column in my c# winform project to show up like an href link. The thing is that the link click works but any average user wouldn't realize that they can click the field since it's displayed as a string. I need the field to show up as blue, with underlines, the mouse pointer turns into a hand ...etc.
I was able to accomplish this previously when I was using Datasets with my Datagrid. I went to the designer and selected "Add Column" and added it as a 'DataGridViewLinkColumn". I've recently changed the project to use datatables and I realized that the fields no longer show up as clickable (if I click it does work though).
Any ideal how to accomplish this with relative ease? I've searched and I'm somewhat surprised that I cannot seem to find a simple solution.
Change the type of the cells that are links to be a DataGridViewLinkCell and then handle the click on the cell, like this:
void dataGridView1_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
{
foreach (DataGridViewRow r in dataGridView1.Rows)
{
if (System.Uri.IsWellFormedUriString(r.Cells["Links"].Value.ToString(), UriKind.Absolute))
{
r.Cells["Links"] = new DataGridViewLinkCell();
DataGridViewLinkCell c = r.Cells["Links"] as DataGridViewLinkCell;
}
}
}
// And handle the click too
private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
if (dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex] is DataGridViewLinkCell)
{
System.Diagnostics.Process.Start( dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value as string);
}
}
This might help:
DataGridViewLinkColumn col1 = new DataGridViewLinkColumn();
dataGridView1.Columns.Add(col1);
dataGridView1.Columns[0].Name = "Links";
DataGridViewRow dgvr = new DataGridViewRow();
dgvr.CreateCells(dataGridView1);
DataGridViewCell linkCell = new DataGridViewLinkCell();
linkCell.Value = #"http:\\www.google.com";
dgvr.Cells[0] = linkCell;
dataGridView1.Rows.Add(dgvr);
it creates a col and then a cell of type link.
you can use foreach loops to do this more orderly and faster for more items.
Good Luck!
Take a look at the DataGridViewLinkColumn.LinkBehavior Property. It can be set to AlwaysUnderline.
As for color, simply use the *LinkColor properties on the DataGridViewLinkColumn.
Cheers
You could just colour that column in the datagridview. You could do this in a DataBindingComplete event like so:
private void dataGridView1_DataBindingComplete(object sender,
DataGridViewBindingCompleteEventArgs e)
{
if(this.mydatagridview.Columns["YourLinkColumnName"] != null)
{
this.mydatagridview.Columns["YourLinkColumnName"].DefaultCellStyle.Font = ...
this.mydatagridview.Columns["YourLinkColumnName"].DefaultCellStyle.ForeColor = ...
}
}
You can set the font to be however you like it (ie. underlined, colored, etc.).
Alternatively, you can change the default cell style in the designer if you have the columns premade (not autogeneratedcolumns).
I have a database that has a Users table and I present the data in a DataGridView. I would like to remove 4 columns, but the code I have (referenced from MSDN) seems to append the columns at the end. How can I totally REMOVE the columns?
So this is how the DGV looks without the columns removed
The Code I use to TRY and remove the columns
RadarServerEntities rse = new RadarServerEntities();
gvUsers.DataSource = rse.Users;
gvUsers.Columns.Remove("ID");
gvUsers.Columns.Remove("InsertDate");
gvUsers.Columns.Remove("Connections");
gvUsers.Columns.Remove("MachineID");
The result
I would like to get rid of the last 4 columns, so why isnt my code doing it?
Many Thanks :)
I tend to just hide the fields instead.
gvUsers.Columns["ID"].Visibility = false;
Et cetera.
you could also use gvUsers.Columns.RemoveAt(IndexOfColumn);
if you don't want to create the columns automatically when you bind your DataSource, you need to set gvUsers.AutoGenerateColumns = false;
RadarServerEntities rse = new RadarServerEntities();
gvUsers.AutoGenerateColumns = false;
gvUsers.DataSource = rse.Users;
To actually remove automatically generated column you have to turn off automatic generation after data binding.
So the code would be:
RadarServerEntities rse = new RadarServerEntities();
gvUsers.DataSource = rse.Users;
gvUsers.AutoGenerateColumns = false;
gvUsers.Columns.Remove("ID");
gvUsers.Columns.Remove("InsertDate");
gvUsers.Columns.Remove("Connections");
gvUsers.Columns.Remove("MachineID");
I haven't checked what exactly happens, but probably the moment DGV becomes visible, missing columns are re-autogenerated.
So with this solution you have columns generated at the moment of binding data, then you turn it off and remove columns that you don't need. Missing columns can't be re-generated.
DataGridViewColumn DataGridViewColumnSelected;
private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
if (e.ColumnIndex !=-1 && e.RowIndex == -1)
{
DataGridViewColumnSelected = dataGridView1.Columns[e.ColumnIndex] as DataGridViewColumn;
}
}
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
bool bHandled = false;
switch (keyData)
{
case Keys.Delete:
if (DataGridViewColumnSelected != null)
{
this.dataGridView1.Columns.RemoveAt(DataGridViewColumnSelected.Index);
//dataGridView1.Columns[DataGridViewColumnSelected.Name].Visible = false; // case of just hiding the column
}
break;
}
return bHandled;
}
I think you have to Modify DataTable before passing it to DGV
as follow:
RadarServerEntities rse = new RadarServerEntities();
rse.Users.Columns.Remove("ID");
rse.Users.Columns.Remove("InsertDate");
rse.Users.Columns.Remove("Connections");
rse.Users.Columns.Remove("MachineID");
dgvUsers.DataSource=rse.Users;
this method worked for me
If what you want is to remove from a DataGridView is the column you have selected then this code is for you.
Place this code in the delete button and ready to delete the column you have selected.
int rowIndex = TuDataGrigView1.CurrentCell.RowIndex;
TuDataGrigView1.Rows.RemoveAt(rowIndex);
I have a datagridview with multiple checkboxes. When the Finished checkbox is checked I need to execute linq code to update a specific table. How do I find out if that specific check box is dirty and where do I write the code to pass the values I need to be passed to the table. Note that it is not the same table that the datagridview is based on.
Thanks.
EDIT:
private void propertyInformationDataGridView_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
DataGridViewCheckBoxCell checkCell = (DataGridViewCheckBoxCell)propertyInformationDataGridView.Rows[e.RowIndex].Cells[3];
DataGridViewRow row = propertyInformationDataGridView.Rows[e.RowIndex] as DataGridViewRow;
System.Data.DataRowView SelectedRowView;
newCityCollectionDataSet.PropertyInformationRow SelectedRow;
SelectedRowView = (System.Data.DataRowView)propertyInformationBindingSource.Current;
SelectedRow = (newCityCollectionDataSet.PropertyInformationRow)SelectedRowView.Row;
if (Convert.ToBoolean(checkCell.EditedFormattedValue) == true)
{
DataClasses1DataContext dc = new DataClasses1DataContext();
var matchedCaseNumber = (from c in dc.GetTable<PropertyInformation>()
where c.CaseNumberKey == SelectedRow.CaseNumberKey
select c).SingleOrDefault();
reportsSent newReport = new reportsSent();
newReport.CaseNumberKey = SelectedRow.CaseNumberKey;
dc.reportsSents.InsertOnSubmit(newReport);
dc.SubmitChanges();
}
}
Do I need to endedit at some point is that the issue?
This is from some of my code, all you need to do is create a "CellContentClick" event for your datagridview.
The easiest way to do this is select the Datagridview, go to properties and click on the lightning bolt. Scroll down to "CellContentClick" and double click in the empty box. This will auto generate the method you need to paste the following code into.
Make sure you rename my instances of "CustomersDataGridView" to whatever yours is named as well, intellisense should highlight invalid code in red that you need to replace.
Also, the "9" you see in the checkCell declaration needs to be changed to the index of your "Finished" check-box. If it is in the 3rd cell from the left, put a 2 there instead of a 9, as the indexing is 0 based.
EDITTED to fix comments:
private void CustomersDataGridView_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
if (e.ColumnIndex.ToString() == "9")
{
DataGridViewCheckBoxCell checkCell = (DataGridViewCheckBoxCell)CustomersDataGridView.Rows[e.RowIndex].Cells[9];
DataGridViewRow row = CustomersDataGridView.Rows[e.RowIndex] as DataGridViewRow;
if (Convert.ToBoolean(checkCell.EditedFormattedValue) && CustomersDataGridView.IsCurrentCellDirty)
{
//Do Work here.
var z = row.Cells[0].Value; // Fill in the brackets with the column you want to fetch values from
//z in this case would be the value of whatever was in the first cell in the row of the checkbox I clicked
}
}
}
You can do it in the CheckedChanged-Event
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
// Do what you have to do...
}
I have an ASP.NET 2.0 (C#) web app, and in it I have a gridview that gets its data from an oracle database.
I want to know how to check if the gridview is empty, and the do something.
I have already tried:
if(GridView.Rows.Count == 0)
{
// Do Something
}
but it doesn't work...
Any ideas?
Thank you.
Your code should work. But only after GridView.DataBind() has been called. Generally I don't check the GridView it's self, but the datasource of the grid view.
DataTable data = DAL.getdata();
if (data.Rows.Count == 0)
{
ShowEmptyData();
}
else
{
Grid.DataSource = dt;
Grid.DataBind();
}
This doesn't work since the GridView is data bound and is going to fetch the actual data at a later time while rendering the page. You should check this by directly querying the data binding source of the gridview (see if the actual list that's grid view bound to is empty or not).
If you just want to display something when it's empty, you should use <EmptyDataTemplate> in your markup:
<asp:GridView runat="server">
<EmptyDataTemplate>The grid is empty</EmptyDataTemplate>
</asp:GridView>
I agree with the other responses. I want to add little information, you should get rows.count after databind method :
int rowCount = GridView.Rows.Count; // returns zero
GridView.DataBind();
rowCount = GridView.Rows.Count; // returns actual row count
If you're using databinding, the the row count of the datasource not the count on the grid itself.
Its very easy: Hope it works for you.. :)
Use event of GridView DataBound: which fires after data is bound.
protected void GridView1_DataBound(object sender, EventArgs e)
{
int rowCount = GridView1.Rows.Count;
if (rowCount == 0)
{
GridView1.Visible = false;
}
else
{
GridView1.Visible = true;
}
}
First create a helper class.
public static class GridViewExtensions
{
public static IEnumerable<GridViewRow> AsEnumerable(this GridView grid)
{
foreach (GridViewRow row in grid.Rows)
{
yield return row;
}
}
public static bool IsEmpty(this GridView grid)
{
return !grid.AsEnumerable().Any(t => t.RowType == DataControlRowType.DataRow);
}
}
Then just call IsEmpty
GridView1.IsEmpty()
In case you've configured your GV to automatically fetch the data from DB, then you may add the following line as the first statement of your GV in Source mode:
<EmptyDataTemplate>No data found.</EmptyDataTemplate>
And then continue with the normal code in your GV.
Based on answers already, GridView.Rows.Count is not enough on its own, depending on the nature of your GridView, especially if it's a dynamic gv, which in most cases it is, plus you have to factor in Paginating, Headers and Footers, which alter the row count.
I use a simple method to tell me ...
//checks if a gridview has any actual rows of data (not just blank rows filled in by the Load
protected bool gvNoData(GridView gv)
{
int wsDataRow = 0;
foreach (GridViewRow gvRow in gv.Rows)
if (gvRow.RowType == DataControlRowType.DataRow)
{
HiddenField hf = (HiddenField)gvRow.FindControl("hfStudentID");
if (hf != null)
if (hf.Value.ToString().Length > 0)
wsDataRow +=1;
}
//if a count was generated then there are data rows, otherwise the rows are blank or nonexistant
if (wsDataRow > 0) return false;
else return true;
}
So running something like this will tell you if the Rows are really "
"DATA" rows, or empty or nothing!
Obviously in my case I have a HiddenField to tell me if the GridViewRow is an actual data row, as I prefill my gridview with blank rows (for my purposes) and some datarows.
However, a simpler version to check based on DataRow vs HeaderRow, etc...
foreach (GridViewRow gvRow in myGridView.Rows)
if (gvRow.RowType == DataControlRowType.DataRow)
{
//do what you need
}
I hope this helps.
In short, there is no GridView.IsEmpty() function unfortunately, unless you enumerate one as shown below.