问题
I've got a gridview with a bunch of template columns. One of those columns is a hidden column that either has a value of 0 or 1. If a row in a grid view is changed I set the value to 1, otherwise I leave the default 0.
The templatefield is defined as:
<asp:TemplateField>
<ItemTemplate>
<input type="hidden" id="rowIsChanged" runat="server" />
</ItemTemplate>
</asp:TemplateField>
My issue is (without too much details), I've got a field where I call a javascript function and do some validation on the client side. Inside of this function I'd like to be able to access this hidden field (rowIsChanged) for this specific row and set the value to 1 (in javascript). That way when I click my server side 'Update' button I can ensure the update occurs given I have a condition checken for rowIsChanged==1
.
So my question, I have something to this effect right now:
<asp:TemplateField>
<ItemTemplate>
<asp:TextBox id="txtMyDate" runat="server" onchange="DoSomeValidation(this)" />
</ItemTemplate>
<asp:TemplateField>
And the javascript:
function DoSomeValidation(myParam)
{
//do some validation...
//here is where I need to access the hidden field 'rowIsChanged' and set the value to "1"
}
So how can I access this particular row's rowIsChanged field and set it to "1".
Edit
Here is more details:
The asp markup:
<asp:TemplateField HeaderText="Date" SortExpression="LineItemDate">
<ItemTemplate>
<ajaxToolkit:CalendarExtender TargetControlID="txtMyDate" ID="CalendarExtender3" runat="server"></ajaxToolkit:CalendarExtender>
<asp:TextBox ToolTip="Line Item Date" Width="60px" ID="txtMyDate" runat="server" Text='<%# DataBinder.Eval(Container, "DataItem.MyDate") %>'></asp:TextBox>
</ItemTemplate>
</asp:TemplateField>
The issue is when I first load the page and load the grid data the system automatically assumes a change was made to the date (value of hidden field is 1). But no changes were made it is just an initial load...So I dont know how to handle this.
In the gridview's row databound event I have the following snippet of code:
If e.Row.RowType = DataControlRowType.DataRow Then
Dim hiddenField As HtmlInputHidden = DirectCast(e.Row.FindControl("rowIsChanged"), HtmlInputHidden)
Dim tLID As TextBox = CType(e.Row.FindControl("txtMyDate"), TextBox)
tLID.Attributes.Add("onchange", "document.getElementById('" + hiddenField.ClientID + "').value=1")
....
So I've posted code for the rowdatabound event as well as the markup..but as soon as the page loads with NO edits done to the field txtMyDate
and I click the "Update" button on my page which does something to this effect:
For Each Row As GridViewRow In Me.gvLineItems.Rows
Dim hiddenField As HtmlInputHidden = DirectCast(Row.FindControl("rowIsChanged"), HtmlInputHidden)
'only update rows that have been edited / update IsDirty=1 :)
If (hiddenField.Value = "1") Then
Every row seems to have the value 1 as if the row was already updated (onchange got called...). But this is not the case. This works fine for any other field that is not using the calendar control. For instance, if I comment the line:
tLID.Attributes.Add("onchange", "document.getElementById('" + hiddenField.ClientID + "').value=1")
And just leave the onchange for all my other fields and then click the "Update" button it works as expected (that is if I change the value in the fields then the hidden field has the value 1 and if i dont change the values in the field they have the value 0). But the issue is just this one field...
Edit 2
Just for testing I even tried this:
Protected Sub gvLineItems_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles gvLineItems.RowDataBound
If e.Row.RowType = DataControlRowType.DataRow Then
'this is used to add a trigger to the <TRIGGERS> tag for the update panel
'I could not do it in the HTML / ASP code because the button is inside of a gridview control
Dim hiddenField As HtmlInputHidden = DirectCast(e.Row.FindControl("hdnIsChanged"), HtmlInputHidden)
'the line item date
Dim tLID As TextBox = CType(e.Row.FindControl("txtMyDate"), TextBox)
'just a test...
tLID.Attributes("onchange") = "helloworld();"
All I did was add a js function called helloworld() that looks like this:
function helloworld()
{
alert ("hello world");
}
I run my project and right away it alerts out hello world (I have 2 rows in the grid so it alerts out hello world twice). This is without any change whatsoever to the data, the question is why is onchange called without any change? It must have to be with how it is setting the date from the the data returned from the database, is that considered an onchange event when it sees markup like so:
<asp:TextBox ToolTip="Line Item Date" ID="txtMyDate" runat="server" Text='<%# DataBinder.Eval(Container, "DataItem.MyDate") %>' />
Specifically the DataBinder.Eval(Container, "DataItem.MyDate")...
Edit #3..Could be possible cause
@Tim
I decided to make a small change, you mentioned in your comments you filled in the txtMyDate statically by assigning a value to it (rather then pulling the value from the database like I did). So instead of this:
<asp:TextBox ToolTip="Line Item Date" ID="txtMyDate" runat="server" Text='<%# DataBinder.Eval(Container, "DataItem.MyDate") %>'
Just for giggles I changed it to this:
<asp:TextBox ToolTip="Line Item Date" Width="60px" ID="txtMyDate" runat="server" Text="1/1/2011">
That is I set the value statically like you did...I run my project and now the alert doesn't fire, hence no onchange
, this is probably why you could not reproduce the error. So it appears this:
<asp:TextBox ToolTip="Line Item Date" ID="txtMyDate" runat="server" Text='<%# DataBinder.Eval(Container, "DataItem.MyDate") %>'
Causes the onchange
event to fire, which for me is not good :(...so question is how to still handle this??
Edit 4!!!
Wow sorry for all the edits, I am trying to eliminate possibilities here... So now what I did was remove this line:
<ajaxToolkit:CalendarExtender TargetControlID="txtMyDate" ID="CalendarExtender3" runat="server"></ajaxToolkit:CalendarExtender>
Meaning I removed the calendarextender from the markup and the onchange event no longer fires on the load event. Why would this be causing this to happen. Even If I leave this:
<asp:TextBox ToolTip="Line Item Date" ID="txtMyDate" runat="server" Text='<%# DataBinder.Eval(Container, "DataItem.MyDate") %>'>
As long as I eliminate the calendarextender it works fine...Did I mention this gridview is inside an updatepanel? Could this be the issue?? The problem is I do not want to remove the calendarextender...I would like to be able to allow users to select a date from that rather then typing it in.
回答1:
You could add the javascript onchange handler from codebehind:
Protected Sub GridView1_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs)
If e.Row.RowType = DataControlRowType.DataRow Then
Dim hidden = DirectCast(e.Row.FindControl("rowIsChanged"), HtmlInputHidden)
Dim txtMyDate = DirectCast(e.Row.FindControl("txtMyDate"), TextBox)
txtMyDate.Attributes("onchange") = "DoSomeValidation(this,'" & hidden.ClientID & "');"
End If
End Sub
C#
protected void GridView1_RowDataBound(object sender, System.Web.UI.WebControls.GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow) {
var hidden = (HtmlInputHidden)e.Row.FindControl("rowIsChanged");
var txtMyDate = (TextBox)e.Row.FindControl("txtMyDate");
txtMyDate.Attributes("onchange") = "DoSomeValidation(this,'" + hidden.ClientID + "');";
}
}
Edit: here is the js-function, it works to set the value and read it after postback:
<script type="text/javascript">
function DoSomeValidation(ctrl, hiddenID) {
var hidden = document.getElementById(hiddenID);
if(ctrl.defaultValue != ctrl.value)
hidden.value = "1";
}
</script>
Edit2: added an additional check for a difference between the current textbox' value and it's defaultValue.
来源:https://stackoverflow.com/questions/6685939/access-hidden-field-within-gridview-control-to-set-a-value-in-javascript