Good day!
I need to dynamycally upload files and display information in gridview.
After file upload, i need to select file type in dropdown.
But after postback i can't access Gridview1 rows, and get selected file types. After postback Gridview1.Rows.Count = 0.
Is it possible to get selected values from DropDownLists?
<asp:GridView ID="GridView1" runat="server" ShowHeader="False" AutoGenerateColumns="false">
<Columns>
<asp:BoundField DataField="FileName" />
<asp:TemplateField HeaderText="FileType">
<ItemTemplate>
<asp:DropDownList runat="server">
<asp:ListItem Value="Val1">Val1</asp:ListItem>
<asp:ListItem Value="Val2">Val2</asp:ListItem>
<asp:ListItem Value="Val3">Val3</asp:ListItem>
</asp:DropDownList>
</ItemTemplate>
</asp:TemplateField>
<asp:CommandField DeleteText="Remove" ShowDeleteButton="true" />
</Columns>
</asp:GridView>
<asp:FileUpload ID="FileUpload" runat="server" onchange="this.form.submit()" />
Thanks
In Page_Load, during PostBack, GridView rows is empty.
protected void Page_Load(object sender, EventArgs e)
{
RestoreForm();
if (IsPostBack && FileUpload.HasFile)
{
AddRow(FileUpload.PostedFile.FileName);
}
FilesGridView.RowDeleting += new GridViewDeleteEventHandler(RemoveFileFromTable);
}
private void AddRow(string file)
{
DataTable dt = (DataTable)Page.Session["Files"];
if (dt == null)
{
AddDataTableToSession();
dt = (DataTable)Page.Session["Files"];
}
DataRow dr = dt.NewRow();
dr["FileName"] = file;
dr["FileType"] = 0;
dt.Rows.Add(dr);
Page.Session["Files"] = dt;
FilesGridView.DataSource = dt;
FilesGridView.DataBind();
}
private void AddDataTableToSession()
{
DataTable dt = new DataTable("Files");
DataColumn dc = new DataColumn("FileName", Type.GetType("System.String"));
dt.Columns.Add(dc);
dc = new DataColumn("FileType", Type.GetType("System.String"));
dt.Columns.Add(dc);
Page.Session["Files"] = dt;
}
private void RemoveFileFromTable(object sender, GridViewDeleteEventArgs e)
{
int recordToDelete = e.RowIndex;
DataTable dt = (DataTable)Page.Session["Files"];
int cn = dt.Rows.Count;
dt.Rows.RemoveAt(recordToDelete);
dt.AcceptChanges();
Page.Session["Files"] = dt;
FilesGridView.DataSource = dt;
FilesGridView.DataBind();
}
Try by changing Ispostback like this.
if (!IsPostBack && FileUpload.HasFile)
{
AddRow(FileUpload.PostedFile.FileName);
}
(or)
if (IsPostBack == false && FileUpload.HasFile)
{
AddRow(FileUpload.PostedFile.FileName);
}
So that, if page load occurs, Your if condition will get true.
You can find the drop down list and update it with the value in the RowDataBOund event of gridview as follows
protected void Page_Load(object sender, EventArgs e)
{
//RestoreForm();
if (IsPostBack && FileUpload.HasFile)
{
AddRow(FileUpload.PostedFile.FileName);
}
else
{
AddDataTableToSession();
}
FilesGridView.RowDeleting += new GridViewDeleteEventHandler(RemoveFileFromTable);
FilesGridView.RowDataBound += KBFilesGridView_RowDataBound;
}
and row databound will be as follows
void KBFilesGridView_RowDataBound(object sender, GridViewRowEventArgs e)
{
DropDownList ddl = e.Row.FindControl("DropDownList1") as DropDownList;
if (ddl != null)
{
DataRow dr= ((DataRowView)e.Row.DataItem).Row;
ddl.SelectedValue = dr["FileType"].ToString();
}
}
Similary you can get the value of dropdown for remove method as well as follows
private void RemoveFileFromTable(object sender, GridViewDeleteEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
DropDownList ddl = e.Row.FindControl("DropDownList1") as DropDownList;
if (ddl != null)
{
if(ddl.SelectedValue == "someValue") doSomeThing();
}
}
}
Related
Please find image. Here's my whole code, I wanted save each row on save button click. I'm able to get value from cell 0 and cell 1 but unable to get value from cell 2 , where I have drop down list selected value.I'm getting default value "Ignore" instead of selected item. So how do I get selected value of drop down list ?
<div>
<asp:GridView ID="GridView2" runat="server" AutoGenerateColumns = "False"
OnRowDataBound = "OnRowDataBound" Width="544px">
<Columns>
<asp:BoundField DataField="Id" HeaderText="Id" />
<asp:BoundField HeaderText="Name" DataField="Name" />
<asp:TemplateField HeaderText = "Mapping" >
<ItemTemplate>
<asp:DropDownList ID="DropDownList1" runat="server" style="font-size: medium; font-family: Cambria" Width="300px">
</asp:DropDownList>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
<br />
<asp:Button ID="Button2" runat="server" Text="Save"
style="font-size: medium; font-family: Cambria" BorderStyle="Groove"
height="32px" Width="116px" onclick="Save_Click" />
</div>
private void BindGrid()
{
DataTable dt = new DataTable();
connection();
cmd = new SqlCommand("Select top 0 * from F3_BC_Product_Mapping_Data", con);
con.Open();
adapter = new SqlDataAdapter(cmd);
ds = new DataSet();
adapter.Fill(ds, "mytable");
int j = 1;
dt.Columns.AddRange(new DataColumn[2] { new DataColumn("Id", typeof(int)), new DataColumn("Name", typeof(string)) });
foreach (DataColumn column in ds.Tables[0].Columns)
{
dt.Rows.Add(j,column.ColumnName);
j++;
}
GridView2.DataSource = dt;
GridView2.DataBind();
con.Close();
}
protected void OnRowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
DropDownList ddlMap = (e.Row.FindControl("DropDownList1") as DropDownList);
DataTable dt = new DataTable();
dt = (DataTable)Session["data"];
for (int i = 0; i < dt.Columns.Count; i++)
{
ddlMap.Items.Add(dt.Columns[i].Caption.ToString());
}
ddlMap.Items.Insert(0, new ListItem("Ignore"));
}
}
protected void Save_Click(object sender, EventArgs e)
{
foreach (GridViewRow gr in GridView2.Rows)
{
string cell_1_Value = GridView2.Rows[gr.RowIndex].Cells[0].Text;
string cell_2_Value = GridView2.Rows[gr.RowIndex].Cells[1].Text;
string cell_3_Value = ((DropDownList)gr.FindControl("DropDownList1")).SelectedItem.Value;
}
}
If you are getting default value then you must see binding code. I think you haven't use if(!Page.IsPostBack) before binding and setting default value in drop down. Try to change OnRowDataBound as below.
protected void OnRowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow && !Page.IsPostBack)
{
DropDownList ddlMap = (e.Row.FindControl("DropDownList1") as DropDownList);
DataTable dt = new DataTable();
dt = (DataTable)Session["data"];
for (int i = 0; i < dt.Columns.Count; i++)
{
ddlMap.Items.Add(dt.Columns[i].Caption.ToString());
}
ddlMap.Items.Insert(0, new ListItem("Ignore"));
}
}
What i am trying to do is that before saving records to database i want to show the records in GridView that is when user fill the text box and click on button the record is to be shown on GridView with serial Number 1 , 2 , 3 ...
So far i have approach this . The first records get added successfully but when adding second record the DataTable give null reference exception . Is this the right approach ? Or is there an easy way to do this . I am using Telerik RadGrid for asp.net .
public DataTable dt;
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
dt = new DataTable();
dt.Columns.Add("Sn#");
dt.Columns.Add("type");
dt.Columns.Add("AccountTitle");
dt.Columns.Add("Description");
dt.Columns.Add("CostCenter");
dt.Columns.Add("Debit");
dt.Columns.Add("Credit");
sno.Text = "1";
}
}
protected void radGridView2_NeedDataSource(object sender, GridNeedDataSourceEventArgs e)
{
dt = AddRow(dt); // call the method to create row
ViewState["dt"] = dt;
dt = (DataTable)ViewState["dt"];
radGridView2.DataSource = dt;
}
private DataTable AddRow(DataTable dt)
{ // method to create row
DataRow dr = dt.NewRow();
dr[0] = sno.Text;
dr[1] = type.Text;
dr[2] = htitle.Text;
dr[3] = disc.Text;
dr[4] = job.SelectedItem.Text;
dr[5] = drr.Text;
dr[6] = crr.Text;
dt.Rows.Add(dr);
return dt;
}
protected void b1_Click(object sender, EventArgs e)
{
DataTable dt = (DataTable)ViewState["dt"];
ViewState["dt"] = AddRow(dt);
radGridView2.Rebind();
Session["cttt"] = Convert.ToInt32(sno.Text)+1;
sno.Text = Session["cttt"].ToString();
}
I have copy your code and change a bit. Due to your dt declared twice. I believe your error will be the DataTable is null
.aspx
<asp:ScriptManager ID="sm" runat="server"></asp:ScriptManager>
<div>
<telerik:RadGrid ID="rg" runat="server" OnNeedDataSource="RadGrid1_NeedDataSource"></telerik:RadGrid>
<br />
<asp:TextBox ID="sno" runat="server"></asp:TextBox><br />
<asp:TextBox ID="type" runat="server" Text="A"></asp:TextBox><br />
<asp:TextBox ID="htitle" runat="server" Text="B"></asp:TextBox><br />
<asp:TextBox ID="disc" runat="server" Text="C"></asp:TextBox><br />
<asp:DropDownList ID="job" runat="server"><asp:ListItem>Yeah</asp:ListItem></asp:DropDownList><br />
<asp:TextBox ID="drr" runat="server" Text="D"></asp:TextBox><br />
<asp:TextBox ID="crr" runat="server" Text="E"></asp:TextBox><br />
<br />
<br />
<asp:Button ID="b1" runat="server" Text="Click" OnClick="b1_Click" />
</div>
</asp:ScriptManager>
.cs
private DataTable dt;
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
sno.Text = "1";
}
}
private DataTable CreateDataTable()
{
dt = new DataTable();
dt.Columns.Add("Sn#");
dt.Columns.Add("type");
dt.Columns.Add("AccountTitle");
dt.Columns.Add("Description");
dt.Columns.Add("CostCenter");
dt.Columns.Add("Debit");
dt.Columns.Add("Credit");
return dt;
}
private DataTable AddRow(DataTable dt1)
{ // method to create row
DataRow dr = dt1.NewRow();
dr[0] = sno.Text;
dr[1] = type.Text;
dr[2] = htitle.Text;
dr[3] = disc.Text;
dr[4] = job.SelectedItem.Text;
dr[5] = drr.Text;
dr[6] = crr.Text;
dt1.Rows.Add(dr);
return dt1;
}
protected void RadGrid1_NeedDataSource(object sender, Telerik.Web.UI.GridNeedDataSourceEventArgs e)
{
rg.DataSource = ViewState["dt"] as DataTable;
}
protected void b1_Click(object sender, EventArgs e)
{
DataTable dt1 = ViewState["dt"] != null ? ViewState["dt"] as DataTable : CreateDataTable();
ViewState["dt"] = AddRow(dt1);
rg.Rebind();
Session["cttt"] = Convert.ToInt32(sno.Text) + 1;
sno.Text = Session["cttt"].ToString();
}
Result
You are creating a variable with the same name as the global variable (dt) in the event b1_click - this is causing the confusion and the error.
protected void b1_Click(object sender, EventArgs e)
{
//Use the global variable dt
//DataTable dt = (DataTable)ViewState["dt"];
dt = (DataTable)ViewState["dt"];
ViewState["dt"] = AddRow(dt);
radGridView2.Rebind(); //Note this would call the NeedDataSource event
Session["cttt"] = Convert.ToInt32(sno.Text)+1;
sno.Text = Session["cttt"].ToString();
}
Another point to note here is that the AddRow method will be called twice on the button click. Once from b1_click event and then again from NeedDataSource event (which gets triggered on radGridView2.Rebind())
I have an editable GridView, which has a AddRow button, on click of which an empty row consisting of text boxes is added.
Whenever I insert values inside these textboxes, and click AddRow or Delete button, the text boxes loose their values.
I am sure, this doesn't happen due to postback, because there's a Save button too, on the click of which the values are normally preserved.
Below is the markup:
<asp:GridView ID="GridView1" runat="server" ShowFooter="true" AutoGenerateColumns="false"
OnRowDeleting="GridView1_RowDeleting">
<Columns>
<asp:TemplateField HeaderText="Col1">
<ItemTemplate>
<asp:TextBox runat="server" ID="txt1"></asp:TextBox>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Col2">
<ItemTemplate>
<asp:TextBox ID="txt2" runat="server"></asp:TextBox>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Col3">
<ItemTemplate>
<asp:TextBox ID="txt3" runat="server"></asp:TextBox>
</ItemTemplate>
<FooterStyle HorizontalAlign="Right" />
<FooterTemplate>
<asp:Button ID="btnAddNewRow" runat="server" Text="AddRow" OnClick="Add" />
</FooterTemplate>
</asp:TemplateField>
<asp:CommandField ButtonType="Button" ShowDeleteButton="true" />
</Columns>
</asp:GridView>
<asp:Button ID="btnSavetoDB" runat="server" Text="save" OnClick="btnSavetoDB_Click" />
Code Behind:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
SetInitialRow();
}
}
//Sets the first empty row to the grid view
private void SetInitialRow()
{
DataTable dt = new DataTable();
DataRow dr = null;
dt.Columns.Add(new DataColumn("Column1", typeof(string)));
dt.Columns.Add(new DataColumn("Column2", typeof(string)));
dt.Columns.Add(new DataColumn("Column3", typeof(string)));
dr = dt.NewRow();
dr["Column1"] = string.Empty;
dr["Column2"] = string.Empty;
dr["Column3"] = string.Empty;
dt.Rows.Add(dr);
//Store the DataTable in ViewState
ViewState["CurrentTable"] = dt;
GridView1.DataSource = dt;
GridView1.DataBind();
}
//Adds a new empty row to the grid view
protected void Add(object sender, EventArgs e)
{
int rowIndex = 0;
if (ViewState["CurrentTable"] != null)
{
DataTable dtCurrentTable = (DataTable)ViewState["CurrentTable"];
DataRow drCurrentRow = null;
if (dtCurrentTable.Rows.Count > 0)
{
for (int i = 0; i < dtCurrentTable.Rows.Count; i++)
{
//extract the TextBox values
TextBox box1 = (TextBox)GridView1.Rows[rowIndex].Cells[0].FindControl("txt1");
TextBox box2 = (TextBox)GridView1.Rows[rowIndex].Cells[1].FindControl("txt2");
TextBox box3 = (TextBox)GridView1.Rows[rowIndex].Cells[2].FindControl("txt3");
drCurrentRow = dtCurrentTable.NewRow();
//drCurrentRow["RowNumber"] = i + 1;
drCurrentRow["Column1"] = box1.Text;
drCurrentRow["Column2"] = box2.Text;
drCurrentRow["Column3"] = box3.Text;
rowIndex++;
}
//add new row to DataTable
dtCurrentTable.Rows.Add(drCurrentRow);
//Store the current data to ViewState
ViewState["CurrentTable"] = dtCurrentTable;
//Rebind the Grid with the current data
GridView1.DataSource = dtCurrentTable;
GridView1.DataBind();
}
}
else
{
Response.Write("ViewState is null");
}
}
//Called on Delete Button click, which is inside a CommanField
protected void GridView1_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
int num = GridView1.Rows.Count;
int index = Convert.ToInt32(e.RowIndex);
if (num > 1)
{
DataTable dt = ViewState["CurrentTable"] as DataTable;
dt.Rows[index].Delete();
ViewState["CurrentTable"] = dt;
GridView1.DataSource = dt;
GridView1.DataBind();
}
}
Initial snapshot:
After AddRow button click:
Where am I going wrong?
Experts please help.
Regards
The problem is that you haven't used Eval in your markup
<asp:TextBox runat="server" ID="txt1" Text='<%# Eval("Column1") %>'></asp:TextBox>
Optimized code-behind. No need of ViewState
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
var table = CreateDataTable();
table.Rows.Add("", "", "");
BindGridView(table);
}
}
//Sets the first empty row to the grid view
private DataTable CreateDataTable()
{
var dt = new DataTable
{
Columns = { "Column1", "Column2", "Column3" }
};
return dt;
}
private void BindGridView(DataTable table)
{
GridView1.DataSource = table;
GridView1.DataBind();
}
private DataTable PopulateTableFromGridView()
{
var table = CreateDataTable();
for (int i = 0; i < GridView1.Rows.Count; i++)
{
//extract the TextBox values
TextBox box1 = (TextBox)GridView1.Rows[i].FindControl("txt1");
TextBox box2 = (TextBox)GridView1.Rows[i].FindControl("txt2");
TextBox box3 = (TextBox)GridView1.Rows[i].FindControl("txt3");
table.Rows.Add(box1.Text, box2.Text, box3.Text);
}
return table;
}
//Adds a new empty row to the grid view
protected void Add(object sender, EventArgs e)
{
var newTable = PopulateTableFromGridView();
newTable.Rows.Add("", "", "");
BindGridView(newTable);
}
//Called on Delete Button click, which is inside a CommanField
protected void GridView1_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
var dt = PopulateTableFromGridView();
dt.Rows[e.RowIndex].Delete();
if (dt.Rows.Count == 0)
{
dt.Rows.Add("", "", "");
}
BindGridView(dt);
}
Links on inline expressions
http://support.microsoft.com/kb/976112
http://weblogs.asp.net/ahmedmoosa/embedded-code-and-inline-server-tags
when admin approve/reject any document once then when admin again login then he/she not be able to approve/reject documents again and dropdownlist will be disabled only for those documents which can be once approve/reject then when admin view any new documents then drop down will be enable and when admin approve/reject this document then it will be disable dropdownlist for not approve /reject again
for this i do this
protected void OnRowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
//Find the DropDownList in the Row
DropDownList abc = (e.Row.FindControl("DropDownList9") as DropDownList);
abc.Enabled = false;
}
}
but this code show me all dropdownlist are disable .
any solution how i will do this?
According to your comment, I assume your DataSource is either DataTable or DataSet.
If so, you want to cast DataItem to DataRowView inside RowDataBound Event to get the value of the status column.
<asp:GridView ID="GridView1" runat="server"
AutoGenerateColumns="False" OnRowDataBound="GridView1_RowDataBound">
<Columns>
<asp:BoundField DataField="Name" HeaderText="Name" />
<asp:TemplateField HeaderText="Status">
<ItemTemplate>
<asp:DropDownList runat="server" ID="DropDownList9">
<asp:ListItem Text="Approve" Value="1" />
<asp:ListItem Text="Reject" Value="2" />
<asp:ListItem Text="Pending" selected="selected" Value="3">
</asp:DropDownList>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
var table = new DataTable();
table.Columns.Add("Id", typeof (int));
table.Columns.Add("Name", typeof (string));
table.Columns.Add("ApproveID", typeof(string));
table.Rows.Add(1, "Jon Doe", "1");
table.Rows.Add(2, "Eric Newton", "2");
table.Rows.Add(3, "Marry Doe", "3");
GridView1.DataSource = table;
GridView1.DataBind();
}
}
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
var item = e.Row.DataItem as DataRowView;
var dropDownList = e.Row.FindControl("DropDownList9") as DropDownList;
// Get value from ApproveID column,
// and check whehter Approve, Reject or others.
switch (item["ApproveID"].ToString())
{
case "1":
case "2":
dropDownList.Enabled = false;
break;
default:
dropDownList.Enabled = true;
break;
}
}
}
You need to access the data item from each row, I am assuming it is available on the object your are binding to the grid, and determine if they have been approved / rejected. If so then you should run you logic to disable:
protected void OnRowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
var yo = (YOUR-OBJECT)e.Row.DataItem;
if(yo.Status !== null OR yo.Status != 'Not Reviewed'){
//Find the DropDownList in the Row
DropDownList abc = (e.Row.FindControl("DropDownList9")
as DropDownList);
abc.Enabled = false;
}
}
}
you can ask on which row you are with this code:
if (e.Row.RowIndex == <aRowNumber>)
{
...
}
I have a GridView with two columns that have capability to be sorted. After its sorted I want to display an image next to a column with Arrow pointing up or down for Asc and Desc sort.
I cannot figure out how to reference an ImageButton object so I can set the ImageButton.ImageUrl to an actual image based on if its Asc and Desc.
Here is my .aspx code:
<Columns>
<asp:TemplateField>
<HeaderTemplate>
<asp:LinkButton ID="Name_SortLnkBtn" runat="server" Text="Name:" ToolTip="Click to Sort Column" CommandName="Sort" CommandArgument="Name" CausesValidation="false" />
<asp:ImageButton ID="Name_SortImgBtn" runat="server" Visible="false" ToolTip="Click to Sort Column" CommandName="Sort" CommandArgument="Name" CausesValidation="false" />
</HeaderTemplate>
<ItemTemplate>
<asp:HyperLink ID="HyperLink1" runat="server" NavigateUrl='<%# "~/TestResults/Diabetes.aspx?ID="+Eval("ID") %>'><%#Eval("Name")%></asp:HyperLink>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField>
<HeaderTemplate>
<asp:LinkButton ID="HouseName_SortLnkBtn" runat="server" Text="House Name:" ToolTip="Click to Sort Column" CommandName="Sort" CommandArgument="House" CausesValidation="false" />
<asp:ImageButton ID="HouseName_SortImgBtn" runat="server" Visible="false" ToolTip="Click to Sort Column" CommandName="Sort" CommandArgument="House" CausesValidation="false" />
</HeaderTemplate>
<ItemTemplate><%#Eval("House")%></ItemTemplate>
</asp:TemplateField>
</Columns>
Help would be great appreciated.
Updated .aspx.cs file:
public partial class Home : System.Web.UI.Page
{
protected _code.SearchSelection _SearchSelection = new _code.SearchSelection();
protected _code.Utils _utils = new _code.Utils();
protected ImageButton sortImage = new ImageButton();
protected void Page_Load(object sender, EventArgs e) {
//if (!IsPostBack) {
Master.FindControl("Home").ID = "active";
GridView1_DataBind();
//Guid ID = new Guid(_SearchSelection.getUserID().Tables[0].Rows[0]["u_ID"].ToString());
//}
}
protected void GridView1_DataBind() {
string selection = string.Empty;
TreeView treeMain = (TreeView)tree.FindControl("treeMain");
if (treeMain.SelectedNode != null)
selection = treeMain.SelectedNode.Text;
else
selection = Session["Selection"].ToString();
DataSet mainData = _utils.getStoreProcedure(new SqlParameter[] { new SqlParameter("#Selection", selection) }, "sp_getTenantsWithDiabetes", ConfigurationManager.ConnectionStrings["TIPS4"].ConnectionString);
Session["MainData"] = mainData.Tables[0];
GridView1.DataSource = mainData.Tables[0];
GridView1.DataBind();
}
protected void GridView1_Sorting(object sender, GridViewSortEventArgs e) {
//Retrieve the table from the session object.
DataTable dt = Session["MainData"] as DataTable;
ImageButton imageButton = new ImageButton();
if (dt != null) {
//Sort the data.
dt.DefaultView.Sort = e.SortExpression + " " + GetSortDirection(e.SortExpression);
//imageButton.ImageUrl = "~/App_Themes/Sugar2006/Images/arrow_up.gif";
//imageButton.Visible = true;
this.GridView1.DataSource = Session["MainData"];
this.GridView1.DataBind();
}
}
private string GetSortDirection(string column) {
// By default, set the sort direction to ascending.
string sortDirection = "ASC";
// Retrieve the last column that was sorted.
string sortExpression = ViewState["SortExpression"] as string;
if (sortExpression != null) {
// Check if the same column is being sorted.
// Otherwise, the default value can be returned.
if (sortExpression == column) {
string lastDirection = ViewState["SortDirection"] as string;
if ((lastDirection != null) && (lastDirection == "ASC")) {
sortDirection = "DESC";
}
}
}
// Save new values in ViewState.
ViewState["SortDirection"] = sortDirection;
ViewState["SortExpression"] = column;
return sortDirection;
}
protected void gridView1_RowDataBound(object sender, GridViewRowEventArgs e) {
if (e.Row.RowType == DataControlRowType.Header) {
var imageButton = (ImageButton)e.Row.FindControl("Name_SortImgBtn");
sortImage = imageButton;
//imageButton.ImageUrl = "~/App_Themes/Sugar2006/Images/arrow_up.gif";
//imageButton.Visible = true;
}
}
To get a reference to the ImageButton defined in your HeaderTemplate, you can wire up the RowDataBound event of the GridView. In the event handler, check if the row is the header row by using the RowType property, and then use the FindControl method to get a reference to the control.
protected void gridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if(e.Row.RowType == DataControlRowType.Header)
{
var imageButton = (ImageButton)e.Row.FindControl("Name_SortImgBtn");
imageButton.ImageUrl = "~/myimage.gif";
}
}
EDIT
I think you're on the right track. I would make the following changes:
protected void GridView1_Sorting(object sender, GridViewSortEventArgs e)
{
//Retrieve the table from the session object.
DataTable dt = Session["MainData"] as DataTable;
if (dt == null) return;
//Sort the data
dt.DefaultView.Sort = e.SortExpression + " " +
GetSortDirection(e.SortExpression);
this.GridView1.DataSource = dt;
this.GridView1.DataBind();
}
There's no need to worry about the ImageButton in the Sorting event handler. The click of the LinkButton in the header will cause a post back, and the Sorting event handler will be called. It will run before the RowDataBound event is triggered (that won't happen until the GridView1.DataBind method is called). Also, the GetSortDirection method will store the sort expression and the sort order in the ViewState. We'll need those values later in the RowDataBound event handler (shown below).
protected void gridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.Header)
{
//Determine sort column and sort order
var column = ViewState["SortExpression"] != null ?
ViewState["SortExpression"].ToString() : string.Empty;
var sortDirection = ViewState["SortDirection"] != null ?
ViewState["SortDirection"].ToString() : string.Empty;
//Find ImageButton based on sort column (return if not found)
var imageButtonID = string.Concat(column, "_SortImgBtn");
var imageButton = e.Row.FindControl(imageButtonID) as ImageButton;
if(imageButton == null) return;
//Determine sort image to display
imageButton.ImageUrl = string.Equals("asc", sortDirection.ToLower()) ?
"~/App_Themes/Sugar2006/Images/arrow_up.gif" :
"~/App_Themes/Sugar2006/Images/arrow_down.gif";
imageButton.Visible = true;
}
}
In this event handler, we'll retrieve the values stored in the ViewState to determine which ImageButton to make Visible and which image url to use based on the sort direction. I made the assumption that you have given the ImageButton controls an ID of the column name plus "_SortImgBtn" (if you do things in this manner you can avoid a switch statement to map the column to the control name). Just make sure that the ImageButton controls have Visible set to false in the front page and the sorting image should be displayed.