I'm creating a GridView wrapper class which retrieves certain bits of data from the database and then displays it. When a row is selected then I raise an event which other classes will listen to. I have also made a method which adds a new column to the GridView which some simple icons in it.
Here is some of my code:
protected override void OnPreRender(EventArgs e)
{
CreateGridView(); // This creates the gridview and sets it properties
PopulateGridView(); // This queries the DB and binds the data
AddIconColumn(gvData.HeaderRow); //Add Icon Column to header
foreach (GridViewRow row in gvData.Rows)
{
AddIconColumn(row); // Add Icon Column to each row
}
}
protected virtual void AddIconColumn(GridViewRow row)
{
if (!ShowIcons) return;
if (row.RowType == DataControlRowType.Header)
{
TableHeaderCell HeaderCell = new TableHeaderCell();
HeaderCell.Text = string.Empty;
row.Cells.AddAt(index, HeaderCell);
}
if (row.RowType == DataControlRowType.DataRow)
{
var NewCell = new TableCell();
var SwitchCell = row.Cells[6] as TableCell;
NewCell.CssClass = columnValueDictionary[SwitchCell.Text];
row.Cells.AddAt(index, NewCell);
}
}
public void gvData_SelectedIndexChanged(object sender, EventArgs e)
{
GridViewRow row = gvData.SelectedRow; // Get the selected row
int selectedID;
var id = row.Cells[2].Text; // When the icon column is enabled, all the cells are empty at this point !
if (int.TryParse(id, out selectedObjID))
{
if (SelectedIDChanged != null)
{
SelectedIDChanged(this, new SelectedIDChangedEventArgs(selectedObjID));
}
}
}
When I add the new column with the icons, the GridView's SelectedIndexChanged method can't retrieve any data from the row. All the cells text is empty during the SelectedIndexChanged event. If I dont add the icon row (by setting ShowIcons to false) then the cells have the correct text during the SelectedIndexChanged changed event.
What could be causing this behaviour?
Related
I have an ASP.NET web app that processes some data from other sites and displays the information in a gridview. I don't know how many rows that gridview is going to have, nor how many columns.
In this gridview I have a templatefield which I used to add a Checkbox.
The rest of the columns are added using a DataTable that I bind to this gridview. The problem now is that after 10 columns, I have an URL which I want to display as a button, or a link. After this link I have x nr of columns.
How do I add this URL which is resting between static columns and dynamic columns, in a GridView with dynamic rows ?
I tried writing a href=link.. in the DataTable but it displays it as text.
I found an article that suggested something with HtmlDecode, but for that to work I would need to use boundfields which set the htmlencode = false..or something like that.
Is there any way of doing this ? or should I just move the link in the itemtemplate that has the checkbox as well and try to set it there ?
You can use the MatchGrid_RowDataBound method to look over the columns and add the buttons as you need.
Here is an example of how to add a button on RowDataBound:
How do I programmatically add a button to a gridview and assign it to a specific code-behind function?
You can use the OnRowDataBound for that. It will insert extra cells into the GridView. You could also insert extra column into the DataTable before binding it to the GridView.
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
//header
if (e.Row.RowType == DataControlRowType.Header)
{
//add 6 cells
for (int i = 1; i <= 6; i++)
{
TableHeaderCell headerCell = new TableHeaderCell();
if (i == 6)
{
headerCell.Text = "URL";
}
else
{
headerCell.Text = "Static " + i;
}
//add the new cell to the gridview
e.Row.Cells.AddAt(i, headerCell);
}
}
//normal row
if (e.Row.RowType == DataControlRowType.DataRow)
{
//cast the current row to a datarowview
DataRowView row = e.Row.DataItem as DataRowView;
//add 6 cells
for (int i = 1; i <= 6; i++)
{
TableCell cell = new TableCell();
if (i == 6)
{
cell.Text = string.Format("<a target=\"_blank\" href=\"{0}\">{0}</a>", row["myURL"]);
}
else
{
cell.Text = "Enter stuff here...";
}
//add the new cell to the gridview
e.Row.Cells.AddAt(i, cell);
}
}
}
I used #Tim Schmelter code (Creating Gridview column Header by loading data from database) for ItemTemplate Checkboxes its working fine but when use HeaderTemplate, I'm getting an error at ITemplate --> CB_DataBinding --> object dataValue = ((DataRowView)container.DataItem)[_columnName]; saying NullReference since DataItem is Null. MyCode:
private void CreateGridColumns()
{
var tblAllowanceGroup = GetAllowanceGroup();
foreach (DataRow row in tblAllowanceGroup.Rows)
{ ...
field.HeaderTemplate = new GridViewCheckBoxTemplate(ListItemType.Header, AllowanceGroupName);
gvEmpSalaryStructure.Columns.Add(field);
}
private void BindGrid()
{
var tblAllowanceGroup = GetAllowanceGroup();
DataSet dsgrid = new DataSet();
DataTable dtgrid = new DataTable();
var empRow = dtgrid.NewRow();
dtgrid.Columns.Add("EmpName");
foreach (DataRow row in tblAllowanceGroup.Rows)
{
String AllowanceGroupName = row.Field<String>("AllowanceName");
//Add column from domain-name
dtgrid.Columns.Add(AllowanceGroupName, typeof(bool));
//CheckBox-Checked is a boolean
//This gives me only Header Text of Gridview
}
I Want GridView dynamically generated Headers which should contain Checkboxes. And want changes should I Make ITemplate CB_DataBinding to work with ListItemType.Header.
And When we check the checkbox in the Header column all the checkboxes in that column should be checked.
Thanks in Advance.
You can use the OnRowDataBound event of the gridview to loop the header row and insert a CheckBox in each Cell.
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.Header)
{
for (int i = 0; i < e.Row.Cells.Count; i++)
{
CheckBox checkBox = new CheckBox();
checkBox.CssClass = "headerCheckBox";
checkBox.ID = "headerCheckBox_" + i;
e.Row.Cells[i].Controls.Add(checkBox);
}
}
}
And now you can bind a jQuery listener to the CheckBox class to handle the checking/unchecking of the entire column.
I am trying to add the column names of a gridview to a dropdown list.
The problem is when I change the datasource of the gridview, it returns empty.
I am not sure whether the event is working properly, as it does not work with/without it.
I wanted to use the DataBindComplete event, but I could not see it so I tried DataBound instead.
private void BindTable()
{
if (ddTableSearch.SelectedIndex == 0)
{
tblCustomerTableAdapter customerAdapter = new tblCustomerTableAdapter();
GridView2.DataSource = customerAdapter.GetData();
GridView2.DataBind();
}
else if (ddTableSearch.SelectedIndex == 1)
{
tblInvoiceTableAdapter invoiceAdapter = new tblInvoiceTableAdapter();
GridView2.DataSource = invoiceAdapter.GetData();
GridView2.DataBind();
}
else if (ddTableSearch.SelectedIndex == 2)
{
tblEstimateTableAdapter estimateAdapter = new tblEstimateTableAdapter();
GridView2.DataSource = estimateAdapter.GetData();
GridView2.DataBind();
}
}
protected void GridView2_DataBound(object sender, EventArgs e)
{
// Populate dropdown with column names
ddColumnSearch.Items.Clear();
for (int i = 0; i < GridView2.Columns.Count; i++)
{
ddColumnSearch.Items.Add(new ListItem(GridView2.Columns[i].ToString()));
}
}
What am I doing wrong?
The databound event runs for each record in the gridview. So one issue is that each time you are clearing out the items you added before. Another issue is that you need to get the data from the EventArgs instead of from the gridview.columns since those are not there until after all the data is bound. I think all you need to do is get the data from the header row:
protected void GridView2_DataBound(object sender, EventArgs e)
{
// Populate dropdown with column names
if(e.Row.RowType != DataControlRowType.Header) return; //only continue if this is hdr row
ddColumnSearch.Items.Clear();
foreach (TableCell cell in e.Row.Cells)
{
ddColumnSearch.Items.Add(new ListItem(cell.Text));
}
}
I have a problem with datagridview in my windows form application.
I set AllowUserToAddRows=true, so on user double click on last blank rows, the selected cell goes in edit mode and when user write something in the textboxcolumn a new row is added.
This is all fine, but now I would that when new row is edit by user(double click) all the fields are filled with default values, for example using values from first row, so I set DefaultValuesNeeded event on my datagridview and in code behind I fill all field in the selected row.
The problem is that now no new row appear on bottom after DefaultValuesNeeded fire.
How can I solve this issue ?
If you have a binding source to your DataGridView, you can call EndCurrentEdit() in the DefaultValuesNeeeded event handler to commit the new row immediately with the default values.
{
dt = new DataTable();
dt.Columns.Add("Cat");
dt.Columns.Add("Dog");
dataGridView1.AllowUserToAddRows = true;
dataGridView1.DefaultValuesNeeded += dataGridView1_DefaultValuesNeeded;
dataGridView1.DataSource = dt;
}
void dataGridView1_DefaultValuesNeeded(object sender, DataGridViewRowEventArgs e)
{
var dgv = sender as DataGridView;
if(dgv == null)
return;
e.Row.Cells["Cat"].Value = "Meow";
e.Row.Cells["Dog"].Value = "Woof";
// This line will commit the new line to the binding source
dgv.BindingContext[dgv.DataSource].EndCurrentEdit();
}
If you don't have a binding source, we cannot using the DefaultValuesNeeded event since it doesn't work. But we can simulated it by capturing the CellEnter event.
{
dataGridView1.Columns.Add("Cat", "Cat");
dataGridView1.Columns.Add("Dog", "Dog");
dataGridView1.AllowUserToAddRows = true;
dataGridView1.CellEnter += dataGridView1_CellEnter;
}
void dataGridView1_CellEnter(object sender, DataGridViewCellEventArgs e)
{
var dgv = sender as DataGridView;
if (dgv == null)
return;
var row = dgv.Rows[e.RowIndex];
if (row.IsNewRow)
{
// Set your default values here
row.Cells["Cat"].Value = "Meow";
row.Cells["Dog"].Value = "Woof";
// Force the DGV to add the new row by marking it dirty
dgv.NotifyCurrentCellDirty(true);
}
}
I am populating a datatable, then binding it to a gridview. Now I'm reading the rows in the grid and coloring the row if value = [x].
The thing when I try to display on the page the row that is colored im getting it duplicated.
Lets say i have colored 1 row but the response.write will be like 100 times the same result.
Below is my code, hope someone can help :
protected void gv1_RowDataBound(object sender, GridViewRowEventArgs e)
{
string alert = Request.QueryString["check"];
// loop over all the Rows in the Datagridview
foreach (GridViewRow row in gv1.Rows)
{
// if condition is met color the row text
if (gv1.Rows[0].Cells[0].Text.ToString() == alert)
{
Session ["fn"] = gv1.Rows[0].Cells[2].Text;
gv1.Rows[0].ForeColor = Color.Red;
}
Response.Write(Session["fn"]);
}
protected void gv1_RowDataBound(object sender, GridViewRowEventArgs e)
{
string alert = Request.QueryString["check"];
if (e.Row.Cells[0].Text.ToString() == alert)
{
Session ["fn"] = e.Rows.Cells[2].Text;
e.Rows.ForeColor = Color.Red;
Response.Write(Session["fn"]);
}
}