GridView does not update values on postback? - c#

I have a gridview with some custom templates:
<asp:GridView ID="gvGroups" runat="server" AutoGenerateColumns="False"
CssClass="table table-hover table-striped" GridLines="None" >
<Columns>
<asp:BoundField DataField="GroupDescription" HeaderText="Name" ReadOnly="True"
SortExpression="GroupDescription" />
<asp:TemplateField HeaderText="Administrator">
<ItemTemplate>
<asp:CheckBox ID="cbAdmin" runat="server"
Checked='<%# Boolean.Parse((Boolean)Eval("IsReadOnly") ? "True" : "False") ? false : true %>'/>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Remove">
<ItemTemplate>
<asp:CheckBox ID="cbRemove" runat="server" />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="ID" SortExpression="GroupID" Visible="False">
<ItemTemplate>
<asp:Label ID="lblID" runat="server" Text='<%# Bind("GroupID") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
I then have a button that I click and that is supposed to change group administration and remove groups that are checked.
Here is the button code:
protected void btnSave_Click(object sender, EventArgs e)
{
foreach (GridViewRow gvr in gvGroups.Rows)
{
CheckBox cbAdmin = (CheckBox)gvr.FindControl("cbAdmin");
CheckBox cbRemove = (CheckBox)gvr.FindControl("cbRemove");
Label lblID = (Label)gvr.FindControl("lblID");
int id;
bool idValid = int.TryParse(lblID.Text,out id);
bool isReadOnly = !cbAdmin.Checked;
if (idValid)
{
Group g = SecurityManager.GetGroup(id);
if (g.IsReadOnly != isReadOnly)
{
bool updateSuccess = SecurityManager.ChangeGroupPermissions(id, isReadOnly);
}
if (cbRemove.Checked)
{
bool removeEmpSuccess = SecurityManager.RemoveEmployeesFromGroup(id);
bool removeSuccess = SecurityManager.RemoveGroup(id);
}
}
}
}
I used the debugger and even when I uncheck admin on all groups, when I look at cbAdmin.Checked, it is still true, which is the same value it started with, thus nothing ever happens.
What could be the problem? Why am I not seeing the updated values on the button postback?
Thanks

You have to call GridView#DataBind() within if(!IsPostBack){ }
Also you need to set AutoPostBack property of the textboxes to "true"

I guess that you're databinding the GridView on postbacks. That will load the data from database again and prevent changes. So ue the PostBack property of the Page:
protected void Page_Load(Object sender, EventArgs e)
{
if(!IsPostBack)
{
DataBindGridView();
}
}

Related

How do I disable LinkButton in gridview based on a value from another column?

I have a status column which includes approved, rejected or cancelled. I have another Actions column which contain link buttons approve and reject. Now if the status is Cancelled, I want the link button to be disabled for that row.
I tried to use GridView1_DataBound event but couldn't figure out the logic.
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
if (Server.HtmlDecode(e.Row.Cells[0].Text.Trim()).Equals("Cancelled"))
{
//OR you can disable it instead of complately hiding it
((LinkButton)GridView1.Rows[e.Row.RowIndex].Cells[0].Controls[0]).Enabled = false;
}
}
}
Method A
The following should work:
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="false">
<Columns>
<asp:BoundField HeaderText="Status" DataField="Status" />
<asp:TemplateField HeaderText="Actions">
<ItemTemplate>
<asp:LinkButton runat="server" Enabled='<%# !(Eval("Status").ToString().Equals("Cancelled")) %>'>Approve</asp:LinkButton>
<asp:LinkButton runat="server" Enabled='<%# !(Eval("Status").ToString().Equals("Cancelled")) %>'>Reject</asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Method B
Nevertheless, if you do insist on the code-behind approach the safest way to access the LinkButton controls is the following:
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="false" OnRowDataBound="GridView1_RowDataBound">
<Columns>
<asp:BoundField HeaderText="Status" DataField="Status" />
<asp:TemplateField HeaderText="Actions">
<ItemTemplate>
<asp:LinkButton ID="ApproveButton" runat="server">Approve</asp:LinkButton>
<asp:LinkButton ID="RejectButton" runat="server">Reject</asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
if (e.Row.Cells[0].Text.Equals("Cancelled"))
{
((LinkButton)e.Row.FindControl("ApproveButton")).Enabled = false;
((LinkButton)e.Row.FindControl("RejectButton")).Enabled = false;
}
}
}
Explanation
Your code doesn't work because the LinkButton controls are not placed in the cell's Controls collection in the way you're expecting them to. Find out yourself by placing a breakpoint inside the inner condition of GridView1_RowDataBound and check out the items of the Controls collection. You'd be surprised!
Maybe you can use this code
<asp:GridView ID="gridView" runat="server" AutoGenerateColumns="False" OnRowDataBound="gridView_RowDataBound">
<Columns>
<asp:BoundField HeaderText="Column1" DataField="Column1" />
<asp:BoundField HeaderText="Column2" DataField="Column2" />
<asp:TemplateField HeaderText="Status">
<ItemTemplate>
<asp:Label runat="server" ID="lblStatus" Text='<%#Bind("Status") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Actions">
<ItemTemplate>
<asp:LinkButton ID="lnkAction" runat="server">Approve</asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
protected void gridView_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
var status = (e.Row.FindControl("lblStatus") as Label).Text;
if (status == "Cancelled")
{
(e.Row.FindControl("lnkAction") as LinkButton).DisableControl("Disabled button.");
}
}
}
And to disable the button you can use an extension method
public static class Extensions
{
public static TControl DisableControl<TControl>(this TControl control, string desableMessage) where TControl : WebControl
{
control.Attributes.Add("disabled", "");
control.Attributes.Add("data-toggle", "tooltip");
control.Attributes.Add("title", disableMessage);
control.Enabled = false;
return control;
}
}

How to get cell value in a GridView on LinkButton Click Event? Or RowCommand?

I Have a GridView which conntains multiple records and couple of Link Buttons Named Edit and Detail. Now i want to Get the Name of the User (NOT Index), when a user click on Detail Link Button. Like "Name", "FatherName" etc
Here is the .aspx code
<asp:GridView ID="dgvEmployeesInformation" runat="server" CssClass=" table table-bordered table-hover table-responsive" DataKeyNames="Id" AutoGenerateColumns="False" OnRowCommand="dgvEmployeesInformation_RowCommand" OnRowDataBound="dgvEmployeesInformation_RowDataBound" AllowPaging="True" AllowSorting="True" OnPageIndexChanging="dgvEmployeesInformation_PageIndexChanging">
<%--1st Column--%>
<Columns>
<asp:BoundField HeaderText="ID" DataField="Id" ControlStyle-BackColor="#0066ff" Visible="False">
<ControlStyle BackColor="#0066FF"></ControlStyle>
</asp:BoundField>
<asp:BoundField HeaderText="Name" DataField="Name" />
<asp:BoundField HeaderText="Employee No" DataField="EmployeeNo" />
<asp:BoundField HeaderText="Father Name" DataField="FatherName" />
<asp:HyperLinkField DataNavigateUrlFields="Id" DataNavigateUrlFormatString="AddEmployeeBasic1.aspx?thid={0}" HeaderText="Update" NavigateUrl="~/AddEmployeeBasic1.aspx" Text="Edit" />
<asp:TemplateField HeaderText="Action" ShowHeader="True">
<ItemTemplate>
<asp:LinkButton ID="lbDelete" runat="server" CausesValidation="False" CommandName="Delete" Text="Delete"></asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField>
<ItemTemplate>
<asp:LinkButton runat="server" ID="lbDetail" OnClick="lbDetail_Click" DataNavigateUrlFields="Id" DataNavigateUrlFormatString="EmployeesDetails.aspx?EmpID={0}" NavigateUrl="~/EmployeesDetails.aspx" HeaderText="Show Detail" Text="Detail"></asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Here is the lbDetail_Click Code
protected void lbDetail_Click(object sender, EventArgs e)
{
GridViewRow clickedRow = ((LinkButton)sender).NamingContainer as GridViewRow;
Label lblUserName = (Label)clickedRow.FindControl("Name");
EmployeeID.EmpName = lblUserName.ToString();
}
When i put my program on Debugging mode, the lblUserName return NULL
Here is the picture.
What i want is that, when a user click on Detail LinkButton, then on lbDetail Click event, it gets the Name of the Employee and store it in a static variable. Following is the picture
I don't understand how to solve this problem. Please help me through this. Your help will be really appreciated.
I would just add data attributes to the details button then get it's values at code behind.
For example:
1.) Add new data-myData='<%# Eval("Name") %>' attribute and its value to button
<asp:TemplateField>
<ItemTemplate>
<asp:LinkButton runat="server" ID="lbDetail" OnClick="lbDetail_Click" Text="Detail" data-ID='<%# Eval("ID") %>' data-myData='<%# Eval("Name") %>' ></asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
2.) Get those data from event handler
protected void lbDetail_Click(object sender, EventArgs e)
{
LinkButton button = (LinkButton)sender;
var name = (string)button.Attributes["data-myData"];
var selectedID = (string)button.Attributes["data-ID"];
Session["selectedID"] = selectedID ;
}
lblUserName is null because it's not a Label, but a BoundField.
What you could do it get the Cell value.
protected void lbDetail_Click(object sender, EventArgs e)
{
GridViewRow clickedRow = ((LinkButton)sender).NamingContainer as GridViewRow;
Label1.Text = clickedRow.Cells[1].Text;
}
Or use a TemplateField that does contain a Label Name
<asp:TemplateField HeaderText="Name">
<ItemTemplate>
<asp:Label ID="Name" runat="server" Text='<%# Eval("Name")%>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
Here is how your code should look:
protected void lbDetail_Click(object sender, EventArgs e)
{
GridViewRow clickedRow = ((LinkButton)sender).NamingContainer as GridViewRow;
var username = clickedRow.Cells[1].Text;
if(string.IsNullOrEmpty(username))
{
return;
}
EmployeeID.EmpName = username;
}

How to add conditional button in template field gridview?

I have one gridview that contains some fields, I want to show button in TemplateField when Process field has value.
Here is my code:
<asp:GridView ID="grdList" PageSize="20" runat="server" DataSourceID="ODList" AllowPaging="True"
AllowSorting="True" PagerSettings-Position="Top" AutoGenerateColumns="False"
ShowFooter="True" ShowHeaderWhenEmpty="True" OnPageIndexChanged="grdList_PageIndexChanged">
<Columns>
<asp:BoundField DataField="MeasureCatalogId" SortExpression="MeasureCatalogId" />
<asp:BoundField DataField="MeasureName" SortExpression="MeasureName" />
<asp:TemplateField SortExpression="Process">
<ItemTemplate>
<asp:Label ID="Label2" runat="server" Text='<%# Bind("Process") %>'></asp:Label>
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="TextBox1" runat="server" Text='<%# Bind("LevelId") %>'></asp:TextBox>
</EditItemTemplate>
</asp:TemplateField>
<asp:TemplateField ShowHeader="False">
<ItemTemplate>
<%if(????????) -- want condition for process!= ""
{
%>
<img class="semPopup" sempopupurl='<%=Constant.AppPath %>/forms/baseform/MeasureProcessFromCatalogForm.aspx?t=2&lid=<%# Eval("LevelId") %>&mid=<%# Eval("MeasureCatalogId") %>'
sempopupwidth="<%=width %>" sempopupheight="<%=height %>"
src="../../App_Themes/images/select2.gif" />
<%} %>
</ItemTemplate>
</asp:TemplateField>
</Columns>
<PagerSettings Position="Top"></PagerSettings>
<PagerStyle CssClass="grid_pager" />
</asp:GridView>
As an alternative to the other recommendations; you could try using a code expression on the field:
<asp:TemplateField ShowHeader="False">
<ItemTemplate>
<img class="semPopup" sempopupurl='<%=Constant.AppPath %>/forms/baseform/MeasureProcessFromCatalogForm.aspx?t=2&lid=<%# Eval("LevelId") %>&mid=<%# Eval("MeasureCatalogId") %>'
sempopupwidth="<%=width %>" sempopupheight="<%=height %>"
src="../../App_Themes/images/select2.gif" Visible='<%# ShowButton(Eval("Process")) %>'/>
</ItemTemplate>
</asp:TemplateField>
I have not tried this out, but it follows a similar pattern to what i have previously used. The code expression calls the codebehind function 'ShowButton' which should return a bool, here you can evaluate the value of process passed in, and if it is to your liking, pass back a true value; otherwise return false and the button will not show.
C#
protected bool ShowButton(object DataItem)
{
//Here you can place as many conditions as you like
//Provided you always return either true or false
if (DataItem != null)
return true;
else
return false;
}
A suggested edit was posed in a similar fashion, however instead of a bool visibility, the visibility setting is altered by string value. I am sure they will add their take too. After all, variety is the spice of life
Use codebehind, make the button visible when appropriate:
protected void gridview1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
DataRow row = ((DataRowView)e.Row.DataItem).Row;
string process = row.Field<string>("Process"); // change type from string to whatever it is
Button btn = (Button) e.Row.FindControl("ButtonID");
btn.Visible = process == "YourProcessValue";
}
}
you can make use of RowDataBoundand than make decision of hiding your control
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
SomeObject mapItem = (SomeObject)e.Row.DataItem;
if(!mapItem.Process)
(e.Row.Cells[3].FindControl("Buttonid") as Button).visible= false;
}
}
or try
<ItemTemplate>
<asp:Button runat="server" Text="Reject"
Visible='<%# ((bool)Eval("Process")) %>' />
</ItemTemplate>

Create hyperlink button cells in gridview using C# asp.net

I am having a GridView in my web page. Which is displaying the data with the columns as Status, Name , Id and Action. My status column always filled with the 3 values(Complete, Queued and Failed) randomly.
Now I want to display this status column values as a link ,If it is having the value either "Failed" or "Queued". But "Complete" status should not be display as a link.
How Can I achive this design during the runtime?
My Code for binding the data into the grid is,
protected void Page_Load(object sender, EventArgs e)
{
DataTable dtActionList = clsactionList.GetADActionList();
grdADActionList.DataSource = dtActionList;
grdADActionList.DataBind();
}
protected void grdADActionList_RowDataBound(object sender, GridViewRowEventArgs e)
{
foreach (GridViewRow gvr in grdADActionList.Rows)
{
if ((gvr.FindControl("Label1") as Label).Text == "Completed")
{
(gvr.FindControl("Label1") as Label).Visible = true;
(gvr.FindControl("HyperLink1") as HyperLink).Visible = false;
}
}
}
using this code I am just simply binding the values in the grid. I am not able to create the Status column as having link buttons based on the binded values for that status column.
My .aspx Code is:
<asp:GridView ID="grdADActionList" runat="server" Height="83px" Width="935px" AutoGenerateColumns="false" OnRowDataBound="grdADActionList_RowDataBound">
<Columns>
<asp:TemplateField HeaderText="Status" SortExpression="Status">
<ItemTemplate>
<asp:HyperLink ID="HyperLink1" runat="server" NavigateUrl='http://localhost:52807/Default.aspx?'><%# Eval("Status") %>
</asp:HyperLink>
<asp:Label ID="Label1" runat="server" Text="<%# Container.DataItem %>" Visible="False"></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="GivenName" HeaderText="GivenName"/>
Please help me to do this further....
On GridViewDataBound event, just hide the link and display a simple label if the value is complete.
ASP.NET:
<asp:TemplateField HeaderText="Status" SortExpression="Status">
<ItemTemplate>
<asp:HyperLink ID="HyperLink1" runat="server" NavigateUrl='your_url'>
<%# Eval("Status") %>
</asp:HyperLink>
<asp:Label ID="Label1" runat="server" Text="<%# Eval("Status") %>" Visible="False"></asp:Label>
</ItemTemplate>
</asp:TemplateField>
C#:
protected void onGridViewDataBound()
{
foreach(GridViewRow gvr in grd)
if((gvr.FindControl("Label1") as Label).Text.ToLower() == "complete") // Updated Line
{
(gvr.FindControl("Label1") as Label).Visible = true;
(gvr.FindControl("HyperLink1") as HyperLink).Visible = false;
}
}
you have to work in design file means .aspx file
you have to use and
<asp:GridView ID="GridView1" runat="server" EnableModelValidation="True">
<asp:TemplateField HeaderText="Hyperlink">
<ItemTemplate>
<asp:HyperLink ID="HyperLink1" runat="server"
NavigateUrl='<%# Eval("CODE", #"http://localhost/Test.aspx?code={0}") %>'
Text='link to code'>
</asp:HyperLink>
</ItemTemplate>
You can place an handler on RowDataBound event
protected void gw_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
DataRowView v_DataRowView = (DataRowView)e.Row.DataItem;
string NavigateUrl = <....place your link here with DataRowView info>
e.Row.Attributes.Add("onclick", NavigateUrl);
}
}
For now you have your columns auto generated, so first disable that feature. Then you need to define each column as a BoundField, and for the hypelink, taking into account your condition, the best way is to define template field:
<asp:GridView ID="grdADActionList" runat="server" BorderStyle="Double" BorderWidth="3px"
Height="83px" Width="935px"
AutoGenerateColumns="false">
<Columns>
<asp:BoundField DataField="Name" HeaderText="Name"/>
<asp:BoundField DataField="Action" HeaderText="Action"/>
<asp:BoundField DataField="Id" HeaderText="Id"/>
<asp:TemplateField HeaderText="Status">
<ItemTemplate>
<asp:HyperLink runat="server" NavigateUrl="~/link/address" Text='<%# Eval("Status") %>'
Visible='<%# (int)Eval("Status") != 1 %>'/>
<asp:Label runat="server" Text='<%# Eval("Status") %>'
Visible='<%# (int)Eval("Status") == 1 %>'>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Note that this is just a variation - you have not specified what values does Status column contain, so I assumed this is int-based enumeration.

update Ajax rating control, update comments

I am trying to update the value of ajaxrating control and comments in the database`
` <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="false" DataKeyNames="id"
onrowdatabound="GridView1_RowDataBound" >
<Columns>
<asp:BoundField HeaderText="PurchasedPID" DataField="PurchasedPID"/>
<asp:BoundField HeaderText="DatetimePurchased" DataField="orderdate" />
<asp:BoundField HeaderText="MMBName" DataField="MMBName" />
<asp:TemplateField HeaderText="Rating">
<ItemTemplate>
<asp:Rating RatingDirection="LeftToRightTopToBottom" Visible="true" AutoPostBack="true"
ID="Rating2" runat="server" MaxRating="5"
StarCssClass="star_rating" EmptyStarCssClass="star_empty"
FilledStarCssClass="star_filled" WaitingStarCssClass="star_saved" CurrentRating='<%# Bind("Rating") %>'
OnChanged="Rating2_Changed" >
</asp:Rating>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Comments">
<ItemTemplate>
<asp:TextBox ID="TextBox1" runat="server" Text= '<%# Bind("Comments") %>' multiline="true">
</asp:TextBox>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Action">
<ItemTemplate>
<asp:LinkButton ID="LinkButton1" runat="server">Submit</asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
So I added the following rowcommand event on of the members suggestion.
protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "Submit")
{
GridViewRow row = (GridViewRow)(((LinkButton)e.CommandSource).NamingContainer);
Int32 Id = Convert.ToInt32(e.CommandArgument);
int ratingScore = ((AjaxControlToolkit.Rating)row.FindControl("Rating2")).CurrentRating;
TextBox TextComments = row.FindControl("TextBox1") as TextBox;
string comments = TextComments.Text;
objBLL.UpdateRating(ratingScore, Id,comments);
}
But here instead of getting the new rating, it is inserting the CurrentRating in the table.
int ratingScore = ((AjaxControlToolkit.Rating)row.FindControl("Rating2")).CurrentRating;
I think its because of this CurrentRating here.
Any idea how to get the value of updated rating? Or should i use an additional Rating_changed event to update the rate, and then a row command event to update the comments
Thanks
Sun
The easiest way to bind the your DataKey/ItemID to the Tag attribute of the Rating control
<asp:Rating RatingDirection="LeftToRightTopToBottom" Visible="true"
AutoPostBack="true"
ID="Rating2" runat="server" MaxRating="5" **Tag='<%# Bind("id")%>'**
StarCssClass="star_rating" EmptyStarCssClass="star_empty"
FilledStarCssClass="star_filled" WaitingStarCssClass="star_saved"
CurrentRating='<%# Bind("Rating") %>'
OnChanged="Rating2_Changed" >
</asp:Rating>
Event Handler
protected void Rating2_Changed(object sender, AjaxControlToolkit.RatingEventArgs e)
{
Rating r = sender as Rating;
int id = Convert.ToInt32(r.Tag);
objBLL.UpdateRating(Convert.ToInt32(e.Value),id)
}
You can use GridView1_RowCommand to update rating score in the DB. e.g.
protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "Rating")
{
GridViewRow row = (GridViewRow)(((ImageButton)e.CommandSource).NamingContainer);
Int32 Id = Convert.ToInt32(e.CommandArgument);
ratingScore = ((AjaxControlToolkit.Rating)row.FindControl("Rating2")).CurrentRating;
}
}
Set CommandName="Rating" to your linkbutton
<asp:TemplateField HeaderText="Action">
<ItemTemplate>
<asp:LinkButton ID="LinkButton1" runat="server" CommandName="Rating">Submit</asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>

Categories

Resources