Dukster131
asked on
Checkbox in Gridview
I want to use a Gridview to get a list of students in a classroom. This list also includes an attendance checkbox and a reason for absence textbox. I want to be able to click on the checkbox in the row to indicate the student is absent and that causes the textbox to be visible. Once the reason is put in the textbox, I want to fire an event that will insert or update the value in the database.
What I have so far is;
<asp:GridView ID="AttendanceGrid" runat="server" AutoGenerateColumns="false "
DataKeyNames="akoEmail" onrowdatabound="Attendance Grid_RowDa taBound">
<Columns>
<asp:TemplateField HeaderText="Name" SortExpression="NameLast">
<ItemTemplate>
<asp:Label ID="lblFN" runat="server" Text='<%# Bind("NameFirst") %>'></asp:Label>
<asp:Label ID="lblLN" runat="server" Text='<%# Bind("NameLast") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Absent" SortExpression="Present" ItemStyle-HorizontalAlign= "Center">
<ItemTemplate>
<asp:CheckBox ID="chkPresent" runat="server" OnCheckedChanged="chkAbsen t_CheckedC hanged"/>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Reason of Absence" SortExpression="roa">
<ItemTemplate>
<asp:TextBox ID="txtReason" runat="server" TextMode="MultiLine" Rows="3" Visible="false" Enabled="false" />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Class Room" SortExpression="Phase1" ItemStyle-HorizontalAlign= "Center">
<ItemTemplate>
<asp:Label ID="lblCR" runat="server" Text='<%# Bind("Phase1") %>' />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
My checkedchanged event is:
protected void chkAbsent_CheckedChanged(o bject sender, EventArgs e)
{
CheckBox chkAbsent = (CheckBox)AttendanceGrid.F indControl ("chkAbsen t");
TextBox txtReason = (TextBox)AttendanceGrid.Fi ndControl( "txtReason ");
if (chkAbsent.Checked)
{
txtReason.Visible = true;
txtReason.Enabled = true;
}
else if(!chkAbsent.Checked)
{
txtReason.Visible = false;
txtReason.Enabled = false;
}
}
What I have so far is;
<asp:GridView ID="AttendanceGrid" runat="server" AutoGenerateColumns="false
DataKeyNames="akoEmail" onrowdatabound="Attendance
<Columns>
<asp:TemplateField HeaderText="Name" SortExpression="NameLast">
<ItemTemplate>
<asp:Label ID="lblFN" runat="server" Text='<%# Bind("NameFirst") %>'></asp:Label>
<asp:Label ID="lblLN" runat="server" Text='<%# Bind("NameLast") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Absent" SortExpression="Present" ItemStyle-HorizontalAlign=
<ItemTemplate>
<asp:CheckBox ID="chkPresent" runat="server" OnCheckedChanged="chkAbsen
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Reason of Absence" SortExpression="roa">
<ItemTemplate>
<asp:TextBox ID="txtReason" runat="server" TextMode="MultiLine" Rows="3" Visible="false" Enabled="false" />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Class Room" SortExpression="Phase1" ItemStyle-HorizontalAlign=
<ItemTemplate>
<asp:Label ID="lblCR" runat="server" Text='<%# Bind("Phase1") %>' />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
My checkedchanged event is:
protected void chkAbsent_CheckedChanged(o
{
CheckBox chkAbsent = (CheckBox)AttendanceGrid.F
TextBox txtReason = (TextBox)AttendanceGrid.Fi
if (chkAbsent.Checked)
{
txtReason.Visible = true;
txtReason.Enabled = true;
}
else if(!chkAbsent.Checked)
{
txtReason.Visible = false;
txtReason.Enabled = false;
}
}
I don't see any event handler for the TextBox.TextChanged event, or something to force the page to post-back (AutoPostBack)...
ASKER
Well, right now i'm trying to get the textboxes to appear when I click the checkbox. Right now when I click a checkbox nothing happens.
In order for the ASP.NET events to fire, the page needs to post-back, so that the event can be detected. Usually, what you use is the AutoPostBack attribute to have the control automatically post back the page.
ASKER
Ok. I figured I had forgotten to do an autopostback. Now I am getting a null exception error. Where am I going to need to check on the checkbox for each row in the gridview? Do I need to do that in the DataBound event? Do I need to do an null check first?
"Now I am getting a null exception error"
Where are you getting that exception?
Where are you getting that exception?
ASKER
I'm getting it when I do the chkAbsent_CheckedChanged
protected void chkAbsent_CheckedChanged(o bject sender, EventArgs e)
{
CheckBox chkAbsent = (CheckBox)AttendanceGrid.F indControl ("chkAbsen t");
TextBox txtReason = (TextBox)AttendanceGrid.Fi ndControl( "txtReason ");
if (chkAbsent.Checked)
{
txtReason.Visible = true;
txtReason.Enabled = true;
}
else if(!chkAbsent.Checked)
{
txtReason.Visible = false;
txtReason.Enabled = false;
}
}
At the if(chkAbsent.Checked) I am getting the message: NullReferenceException was unhandled by user code.
protected void chkAbsent_CheckedChanged(o
{
CheckBox chkAbsent = (CheckBox)AttendanceGrid.F
TextBox txtReason = (TextBox)AttendanceGrid.Fi
if (chkAbsent.Checked)
{
txtReason.Visible = true;
txtReason.Enabled = true;
}
else if(!chkAbsent.Checked)
{
txtReason.Visible = false;
txtReason.Enabled = false;
}
}
At the if(chkAbsent.Checked) I am getting the message: NullReferenceException was unhandled by user code.
It is probably because of this line:
CheckBox chkAbsent = (CheckBox)AttendanceGrid.F indControl ("chkAbsen t");
Are these static controls (defined in HTML), or dynamic controls (added in code)?
CheckBox chkAbsent = (CheckBox)AttendanceGrid.F
Are these static controls (defined in HTML), or dynamic controls (added in code)?
ASKER
These controls are in the GridView and generated from the database. I'm hoping to be able to do this in GridView with a checkbox in the item template and a textbox in the item template. This is generated from a view that uses an outer join, so there are definitely null values in the database. In actuality one of the tables that is used to generate this view is the table that the results will go into based upon who is checked.
Is this the CheckBox?
<ItemTemplate>
<asp:CheckBox ID="chkPresent" runat="server" OnCheckedChanged="chkAbsen t_CheckedC hanged"/>
</ItemTemplate>
In 'chkAbsent_CheckedChanged' , the sender variable is 'chkPresent'.
You can get a reference like this:
CheckBox chkAbsent = (CheckBox)AttendanceGrid.F indControl ("chkPrese nt");
--or--
CheckBox chkPresent = (CheckBox)sender;
<ItemTemplate>
<asp:CheckBox ID="chkPresent" runat="server" OnCheckedChanged="chkAbsen
</ItemTemplate>
In 'chkAbsent_CheckedChanged'
You can get a reference like this:
CheckBox chkAbsent = (CheckBox)AttendanceGrid.F
--or--
CheckBox chkPresent = (CheckBox)sender;
ASKER
Yes, that is it. You are correct in that it should have been FindControl("chkPresent"), however, after changing that I still get the same message about NullReferenceException was unhandled by user code.
Did you try the other one?
CheckBox chkPresent = (CheckBox)sender;
CheckBox chkPresent = (CheckBox)sender;
ASKER
Same result.
ASKER
Actually, the error doesn't occur on the Checkbox, but on the Textbox now. So this is progress.
You should be use the GridView row, and not the top-level GridView with FindControl. You should be able to get the current row from the SelectedIndex property:
GridViewRow row = AttendanceGrid.Rows[Attend anceGrid.S electedInd ex];
TextBox txtReason = (TextBox)row.FindControl(" txtReason" );
GridViewRow row = AttendanceGrid.Rows[Attend
TextBox txtReason = (TextBox)row.FindControl("
ASKER
When I do the GridViewRow row = AttendanceGrid.Rows[Attend anceGrid.S electedInd ex];
it raises the ArgumentOutOfRangeExceptio n was unhandled by user code.
it raises the ArgumentOutOfRangeExceptio
That would mean that SelectedIndex is -1.
I set up a small test page, and here is an example of what I would suggest for a solution:
protected void chkSelect_CheckChecked(obj ect sender, EventArgs e)
{
CheckBox chkSelect = (CheckBox)sender;
TextBox firstName = (TextBox)chkSelect.Parent. Parent.Fin dControl(" FirstName" );
TextBox lastName = (TextBox)chkSelect.Parent. Parent.Fin dControl(" LastName") ;
}
You can get the CheckBox.Parent.Parent to get the GridViewRow.
I set up a small test page, and here is an example of what I would suggest for a solution:
protected void chkSelect_CheckChecked(obj
{
CheckBox chkSelect = (CheckBox)sender;
TextBox firstName = (TextBox)chkSelect.Parent.
TextBox lastName = (TextBox)chkSelect.Parent.
}
You can get the CheckBox.Parent.Parent to get the GridViewRow.
<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:AdventureWorksConnectionString %>" SelectCommand="SELECT EmployeeID, Title, FirstName, LastName FROM HumanResources.vEmployee"></asp:SqlDataSource>
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataSourceID="SqlDataSource1">
<Columns>
<asp:TemplateField HeaderText="LastName" SortExpression="LastName">
<ItemTemplate>
<asp:TextBox ID="LastName" runat="server" Text='<%# Eval("LastName") %>' />
<asp:TextBox ID="FirstName" runat="server" Text='<%# Eval("FirstName") %>' />
<asp:CheckBox ID="chkSelect" runat="server" OnCheckedChanged="chkSelect_CheckChecked" AutoPostBack="true" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
ASKER
I do not have the AdventureWorks Database.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Sorry. I misunderstood what you were saying. that worked great. So tell me if you will, how does this TextBox txtReason = (TextBox)chkAbsent.Parent. Parent.Fin dControl(" txtReason" ); work?
I'm still learning .net and this one is interesting to me. Any good references would be appreciated.
I'm still learning .net and this one is interesting to me. Any good references would be appreciated.
The Parent property is the containing element on the page. You can chain these calls together.
In order to understand that concept, break it down into steps.
control.Parent = cell
cell.Parent = row
Simplified HTML representation:
<table>
<tr>
<td><asp:CheckBox /></td>
</tr>
<table>
<td> = cell
<tr> = row
In order to understand that concept, break it down into steps.
control.Parent = cell
cell.Parent = row
Simplified HTML representation:
<table>
<tr>
<td><asp:CheckBox /></td>
</tr>
<table>
<td> = cell
<tr> = row
ASKER
Ok. Thanks. That helps. One more thing. The one other thing I am going to need is the dataKey information(that is my userID) for the row. That way when they enter a reason I will be able to get all the relevant information for the Attendance Table. I know in the GridView itself the value is {0}.
If your GridView is bound to a data source, then you should be able to get the DataItem from the GridViewRow:
DataRowView drv = row.DataItem as DataRowView;
string primaryKey = row[AttendanceGrid.DataKey Names];
DataRowView drv = row.DataItem as DataRowView;
string primaryKey = row[AttendanceGrid.DataKey
ASKER
When I type row I get an error message saying it doesn't exist in the current context. I need to get the dataKeyName for the row that I am doing the checkbox and textbox in. Is there a namespace or class that needs to be referenced to do what you are saying or does it need to happen in a different place?
Aaah, the never-ending question...
If row.DataItem is null, then when the page posts back, the data source is not reset. Usually, I store the DataTable in a Session variable, and set the data source back in the Page_Load:
if (Page.IsPostBack)
{
this.GridView1.DataSource = (DataTable)Session["MyTabl e"];
this.GridView1.DataBind();
}
If row.DataItem is null, then when the page posts back, the data source is not reset. Usually, I store the DataTable in a Session variable, and set the data source back in the Page_Load:
if (Page.IsPostBack)
{
this.GridView1.DataSource = (DataTable)Session["MyTabl
this.GridView1.DataBind();
}
ASKER
If you do that, won't you lose any of the information that has been filled in - won't it revert to what is in the database, or not in the database yet?
Just seems like their should be a way to get the datakey information for the row just like getting the checked value or text value.
Just seems like their should be a way to get the datakey information for the row just like getting the checked value or text value.
If you make sure that the DataTable in the Session variable is current, then nothing will be lost. You should create a small, test web site to see what I mean. You can also get that information from a cell, but only if it is included in the rendered output.
ASKER
I decided to put a label in the gridview with with the userid information and get it the same way that I am getting the textbox information. Thus:
Label lblAKO = (Label)chkAbsent.Parent.Pa rent.FindC ontrol("lb lAKO");
string strAKO = lblAKO.Text;
That way I have the information in a variable and can use it to update the database.
Thanks for all the help.
Label lblAKO = (Label)chkAbsent.Parent.Pa
string strAKO = lblAKO.Text;
That way I have the information in a variable and can use it to update the database.
Thanks for all the help.