Disabling ButtonField when BoundField is zero - c#

I have this GridView that fills on the Page_Load:
protected void Page_Load(object sender, EventArgs e) {
if (!Page.IsPostBack) {
GridView1.DataSource = actBO.BuscarActividades();
GridView1.DataBind();
}
}
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" >
<Columns>
<asp:BoundField DataField="Id" HeaderText="ID" Visible="False" />
<asp:BoundField DataField="Class" HeaderText="Class" />
<asp:BoundField DataField="Day" HeaderText="Day" />
<asp:BoundField DataField="Time" HeaderText="Time" />
<asp:BoundField DataField="Vacants" HeaderText="Vacants" />
<asp:ButtonField ButtonType="Button" HeaderText="Book" Text="Book"/>
</Columns>
</asp:GridView>
Where column "Vacants" shows an int (it represents the amount of vacant booking spaces in a class).
Every row will have a button to book a specific class. I need to place a condition for when the field "Vacants" is zero, so the "Book" button will be disabled.
So far this is what it looks like: image.
As you can see, I need the button to be disabled when there are no more vacants. It shouldn't be able to be clicked.

To do so, you must register OnRowDataBound event. More explanations can be found in here.
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" OnRowDataBound="GridView1_RowDataBound">
<Columns>
<asp:BoundField DataField="Id" HeaderText="ID" Visible="False" />
<asp:BoundField DataField="Class" HeaderText="Class" />
<asp:BoundField DataField="Day" HeaderText="Day" />
<asp:BoundField DataField="Time" HeaderText="Time" />
<asp:BoundField DataField="Vacants" HeaderText="Vacants" />
<asp:ButtonField ButtonType="Button" HeaderText="Book" Text="Book"/>
</Columns>
</asp:GridView>
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
// get your button via the column index; ideally you could use template field and put your own button inside
var button = e.Row.Cell[5].Controls[0] as Button;
int vacant = 0;
var vacantVal = int.TryParse(e.Row.Cell[4].Text, out vacant);
if (button != null)
{
button.Enabled = vacant > 0;
}
}
}
Hope it helps.

Related

How do I get the value of a particular row in my Gridview

I have a Gridview which also contains a button field. When this button on a particular row is clicked, I want it to update my database. For example, if a row contains (SN = 1) I want it to update the button to update the database with the row that contains "SN = 1". How do I get the SN of the row when the button on that same row is clicked?
This is my Gridview definition:
<asp:GridView ID="GridView1" runat="server" AllowPaging="True" Height="326px" OnPageIndexChanging="GridView1_PageIndexChanging" PageSize="5" style="text-align: left; margin-left: 169px" Width="1069px" OnSelectedIndexChanged="GridView1_SelectedIndexChanged" OnRowDataBound="GridView1_RowDataBound" AutoGenerateColumns="False" OnRowCommand="GridView1_RowCommand">
<Columns>
<asp:BoundField HeaderText="S/N" DataField="SN" />
<asp:BoundField HeaderText="First Name" DataField="FirstName" />
<asp:BoundField HeaderText="Address" DataField="Address" />
<asp:BoundField HeaderText="Phone Number" DataField="PhoneNumber" />
<asp:BoundField HeaderText="Sex" DataField="Sex" />
<asp:BoundField HeaderText="Reason" DataField="Reason" />
<asp:BoundField HeaderText="SignIn" DataField="SignIn_Time" />
<asp:BoundField HeaderText="SignOut" DataField="Signout_Time" />
<asp:TemplateField HeaderText="Action">
<ItemTemplate>
<asp:Button ID="out" runat="server" Text="Sign out" CommandName="SignOut"/>
</ItemTemplate>
</asp:TemplateField>
</Columns>
<PagerSettings FirstPageText="First" LastPageText="Last" Mode="NumericFirstLast" PageButtonCount="5" />
</asp:GridView>
Here, when the row button is clicked, I want to update my database with the signout time. I can't seem to get it to get the SN of the row and update.
protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "SignOut")
{
}
}
If the value you seek is the comes from the same datasource, you can add the value as a CommandArgument:
<asp:TemplateField HeaderText="Action">
<ItemTemplate>
<asp:Button ID="out"
runat="server"
Text="Sign out"
CommandName="SignOut"
CommandArgument='<%# Eval("SN") %>'/>
</ItemTemplate>
</asp:TemplateField>
On your code behind:
protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "SignOut")
{
string sn = e.CommandArgument.ToString();
if (sn == "1")
{
/*DO STUFF....*/
}
}
}

How to show and hide a button field in gridview if a row contains an empty cell

i have a gridview in my asp.net application. for example
SN name Date Action
1 mike button(do something)
This is just one out of my gridview rows. I want for every row that has an empty cell, button field cell for the row should show. If there's no empty cell in that row, the button should hide. What i get with my code is that all the button visible becomes false which i do not want.
Here is my code behind
<asp:GridView ID="GridView1" runat="server" AllowPaging="True" Height="326px" OnPageIndexChanging="GridView1_PageIndexChanging" PageSize="5" style="text-align: left; margin-left: 169px" Width="1069px" OnSelectedIndexChanged="GridView1_SelectedIndexChanged" OnRowDataBound="GridView1_RowDataBound" AutoGenerateColumns="False" OnRowCommand="GridView1_RowCommand" OnRowEditing="GridView1_RowEditing">
<Columns>
<asp:BoundField HeaderText="S/N" DataField="SN" />
<asp:BoundField HeaderText="First Name" DataField="FirstName" />
<asp:BoundField HeaderText="Address" DataField="Address" />
<asp:BoundField HeaderText="Phone Number" DataField="PhoneNumber" />
<asp:BoundField HeaderText="Sex" DataField="Sex" />
<asp:BoundField HeaderText="Reason" DataField="Reason" />
<asp:BoundField HeaderText="SignIn" DataField="SignIn_Time" />
<asp:BoundField HeaderText="SignOut" DataField="Signout_Time" />
<asp:TemplateField HeaderText="Action" Visible="True">
<ItemTemplate>
<asp:Button ID="out" runat="server" Text="Sign out" CommandName="SignOut" CommandArgument='<%# Eval("SN") %>' CssClass="active"/>
</ItemTemplate>
</asp:TemplateField>
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
for (int i =0 ; i < e.Row.Cells.Count; i ++)
{
if (e.Row.Cells[i].Text == " ")
{
Button status = (Button)e.Row.FindControl("out");
status.Visible = true;
}
else
{
Button status = (Button)e.Row.FindControl("out");
status.Visible = false;
}
}
}
}
try with this code
string.IsNullOrEmpty(e.Row.Cells[i].Text)
or
e.Row.Cells[i].Text.Equals(" ")
What you are doing is checking all cells inside entire grid. The fix is to check all cells inside each RowDataBound event.
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
var status = (Button) e.Row.FindControl("out");
// Show button if at least one cell is empty.
status.Visible = e.Row.Cells.Cast<TableCell>()
.Any(cell => string.IsNullOrEmpty(cell.Text));
}
}
Normally, database should not return for empty data, unless you intentionally store them in database.

Delete data row from sql in a gridview

I am trying to delete data from a gridview using a a link button. I need help with the logic and making the link button remove the row data from the database on click.
GridView
<asp:GridView Style="width: 100%" ID="GvReportResults" runat="server" AutoGenerateColumns="False" EmptyDataText="No data" ShowHeaderWhenEmpty="True">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:LinkButton ID="lnkBtnEdit" runat="server" CausesValidation="false" >Edit</asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField>
<ItemTemplate>
<asp:LinkButton ID="LnkBtnRemove" runat="server" CausesValidation="false" CommandName="DeleteItem" CommandArgument='<%# Eval("OtherDataID") %>'>Delete</asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="SourceID" HeaderText="ID" />
<asp:BoundField DataField="LastName" HeaderText="Last Name" />
<asp:BoundField DataField="FirstName" HeaderText="First Name" />
<asp:BoundField DataField="MiddleName" HeaderText="Middle Name" />
<asp:BoundField DataField="Title" HeaderText="Title" />
<asp:BoundField DataField="NationalID" HeaderText="SSN" />
<asp:BoundField DataField="DOB" HeaderText="DOB" />
<asp:BoundField DataField="HireDate" HeaderText="Hire Date" />
<asp:BoundField DataField="Address1" HeaderText="Address" />
<asp:BoundField DataField="City" HeaderText="City" />
<asp:BoundField DataField="State" HeaderText="State" />
<asp:BoundField DataField="PostalCode" HeaderText="Zip Code" />
</Columns>
</asp:GridView>
Store precedure thats importing data to gridview
private void BindGrid()
{
//set up arguments for the stored proc
int? FacilityID = (ddlFacility2.SelectedValue.Equals("-1")) ? (int?)null : int.Parse(ddlFacility2.SelectedValue);
int? OtherDataID = null;
//bind
GvReportResults.DataSource = this.DataLayer.model.MS_spGetOtherData(FacilityID, OtherDataID);
GvReportResults.DataBind();
}
Add OnClick attribute for the LinkButton, for example (added OnClick to your linkbutton code)
<asp:LinkButton ID="LnkBtnRemove" runat="server" CausesValidation="false" CommandName="DeleteItem" CommandArgument='<%# Eval("OtherDataID") %>' OnClick='LnkBtnRemove_Click'>Delete</asp:LinkButton>
Have OnClick listener as
protected void LnkBtnRemove_Click(object sender,EventArgs e)
{
string id = ((LinkButton)sender).CommandArgument;//CommandArgument is always returns string
Do_DeleteRow(id);//method to delete
BindGrid();
}
private void Do_DeleteRow(string id)
{
//your delete code will be added here
}
Just attach ItemCommand event to your grid
On web page in your grid definition add:
<asp:DataGrid OnItemCommand="Grid_ItemCommand" />
after that in code behind:
void Grid_ItemCommand(Object sender, DataGridCommandEventArgs e)
{
var id = Int32.Parse(e.CommandArgument.ToString()); //use parse if OtherDataID is int
//here goes logic for deleting row
this.DataLayer.model.spDeleteData(id);
//after deleting rebind grid
BindGrid();
}
Convert your boundfiled into Item Template, Here using sourceid will fire delete Query.
Code look like this:
protected void GvReportResults_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "DeleteItem")
{
int getrow = Convert.ToInt32(e.CommandArgument);
Label lblSourceID = (Label)GvReportResults.Rows[getrow].FindControl("lblSourceID");
bool flag=deleteRecord(lblSourceID.text);
if(flag)
{
succes msg!
}
else{ failed msg}
}
}
public bool deleteRecord(String SourceID)
{
try
{
SqlCommand cmd = new SqlCommand("Your Delete Query where condtion ", conn);
conn.Open();
cmd.ExecuteNonQuery();
conn.Close();
return true;
}
catch(Exception ac)
{
return false;
}
}

Accessing data from a BoundField of Gridview

I have a GridView like this
<asp:GridView ID="gv_FilesList" runat="server" AutoGenerateColumns="false" onrowcommand="gv_FilesList_RowCommand">
<Columns>
<asp:BoundField DataField="f_Id" Visible="false" HeaderText="File Name" />
</Columns>
<Columns>
<asp:BoundField DataField="f_Name" HeaderText="File Name" />
</Columns>
<Columns>
<asp:ButtonField ButtonType="Link" Text="Download" CommandName="DownloadFile" HeaderText="Download" />
</Columns>
</asp:GridView>
Now when I click on the download Button, how can I get the corresponding f_Id in order to get the related data from Database.
This code should work, tested on my local.
First, add DataKeyNames to your GridView.
<asp:GridView ID="gv_FilesList" runat="server" AutoGenerateColumns="false" onrowcommand="gv_FilesList_RowCommand" DataKeyNames="f_Id">
<Columns>
<asp:BoundField DataField="f_Id" Visible="false" HeaderText="File Name" />
</Columns>
<Columns>
<asp:BoundField DataField="f_Name" HeaderText="File Name" />
</Columns>
<Columns>
<asp:ButtonField ButtonType="Link" Text="Download" CommandName="DownloadFile" HeaderText="Download" />
</Columns>
</asp:GridView>
Then, access DataKeys from codebehind.
protected void gv_FilesList_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "DownloadFile")
{
//row index
int index = Convert.ToInt32(e.CommandArgument);
//retrieve f_Id
int f_Id = Convert.ToInt32(gv_FilesList.DataKeys[index].Value);
//download file with f_Id
DownloadFile(f_Id);
}
}
A couple of ways to skin it, but you could access it like below:
void gv_FilesList_RowCommand(Object sender, GridViewCommandEventArgs e) {
if(e.CommandName=="DownloadFile")
int index = Convert.ToInt32(e.CommandArgument);
GridViewRow row = gv_FilesList.Rows[index];
string fileDownloadId = row.Cells[1].Text;
//Pull from DB
}
And then add f_id, to the DataKeyNames attribute so it will store the hidden fields value.
<asp:GridView ID="gv_FilesList" runat="server" AutoGenerateColumns="false" onrowcommand="gv_FilesList_RowCommand" DataKeyNames="f_id">
DataKeyNames
A solution to your problem is described in this thread.
Basically you can access the row index in the event argument property called CommandArgument.

Checkbox in TemplateField in Gridview loses checked on postback

I have a gridview with a template field. In that template field is a checkbox. I have a submit button outside of the gridview to assign the records that were checked. On the postback no checkboxes register as being checked. Here is my Code:
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:CheckBox ID="cb" Checked="false" runat="server" />
<asp:Label ID="lblCFID" runat="server" Visible="false" Text='<%# Eval("ID") %>' />
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField HeaderStyle-HorizontalAlign="Center" DataField="Name" HeaderText="Name" />
<asp:BoundField HeaderStyle-HorizontalAlign="Center" DataField="DOB" HeaderText="Date of Birth" />
<asp:BoundField HeaderStyle-HorizontalAlign="Center" HeaderText="Gender" DataField="Gender" />
<asp:BoundField HeaderStyle-HorizontalAlign="Center" HeaderText="Status" DataField="Status" />
<asp:BoundField HeaderStyle-HorizontalAlign="Center" HeaderText="Plan Name" DataField="PlanName" />
<asp:BoundField HeaderStyle-HorizontalAlign="Center" HeaderText="Type" DataField="ControlType" />
<asp:BoundField HeaderStyle-HorizontalAlign="Center" HeaderText="Date of Service" dataformatstring="{0:MMMM d, yyyy}" htmlencode="false" DataField="DateofService" />
</Columns>
protected void AssignRecords(object sender, EventArgs e)
{
int Rows = gvASH.Rows.Count;
for (int i = 0; i < Rows; i++)
{
//CheckBoxField cb = ((CheckBoxField)gvASH.Rows[i].Cells[1]).;
CheckBox cb = (CheckBox)gvASH.Rows[i].Cells[0].FindControl("cb");
Label lblID = (Label)gvASH.Rows[i].Cells[0].FindControl("lblCFID");
if (cb.Checked == true)
{
string ID = lblID.Text;
//Assign Code
}
}
}
I have a breakpoint set on the string ID = lblID.Text; but it never finds any that are checked.
I think what you are missing is, when you click on the button and your page is postback, you rebinding to gridview, you need to bind in this condition like
if (!Page.IsPostBack)
{
GridView1.DataSourceID = "yourDatasourceID";
GridView1.DataBind();
}
On a postback, the contents of the GridView are re-created from the postback Viewstate data between page_init and page_load. Perhaps try examining your Gridview in page_load to see what's there.
set the autopostback attribute of Checkbox
AutoPostBack="true"

Categories

Resources