In a FormView, how to change the property of a Label in the ItemTemplate?
In ASP.NET, I have a FormView which is bound to an ObjectDataSource. The FormView has an ItemTemplate with a Delete button, and a Label. I'm handling the OnItemDeleted event of the FormView to detect if my business class throws an exception upon deletion. If an exception is detected, I change the text of the Label to whatever the exception message is.
Well, it's just not working.
I detect the Exception fine, but the Text of the Label never gets changed. When the page reloads, the default text stays. I have also tri开发者_开发问答ed to rebind the FormView with DataBind() after assigning the new Text, but it's not working either.
In a desperate attempt at tracking the problem, I've taken the Label out of the FormView and it's working fine.
What I am doing wrong?
ASPX page:
<asp:ObjectDataSource ID="MyObjectDataSource"
TypeName="MyScopeRepository"
SelectMethod="GetById"
DeleteMethod="Delete"
runat="server">
<SelectParameters>
<%-- The id param here is from a DropDownList, not included in the example for clarity. --%>
<asp:ControlParameter Name="id" Type="Int32" ControlID="MyDropDownList" PropertyName="SelectedValue" />
</SelectParameters>
<DeleteParameters>
<asp:Parameter Name="id" Type="Int32" />
</DeleteParameters>
</asp:ObjectDataSource>
<asp:FormView ID="MyFormView" DataSourceID="MyObjectDataSource"
RenderOuterTable="false"
DataKeyNames="Id"
OnItemDeleted="MyFormViewItemDeleted"
runat="server">
<ItemTemplate>
<asp:Button CssClass="Button Small" Text="Delete" CommandName="Delete" runat="server" /><br />
<asp:Label ID="ErrorLabel" Text="Default text" runat="server" />
</ItemTemplate>
</asp:FormView>
Code-behind:
protected void MyFormViewItemDeleted(object sender, FormViewDeletedEventArgs e)
{
if (e.Exception != null && e.Exception.InnerException is RepositoryException)
{
Label errorLabel = (Label)MyFormView.FindControl("ErrorLabel");
errorLabel.Text = e.Exception.InnerException.Message;
e.ExceptionHandled = true;
// I also tried this to no avail.
//MyFormView.DataBind();
}
}
Thanks a lot!
EDIT: I've checked all events fired by the FormView when clicking the Delete button and here is what I got:
- OnInit
- OnItemCreated
- OnLoad
- OnItemCommand
- OnItemDeleting
- OnItemDeleted
- OnItemCreated
- OnDataBound
- OnPreRender
- OnUnload
So we can see that OnItemCreated gets fired twice, and the second time it's fired is AFTER OnItemDeleted, which means that whatever change I make is overwritten, I suppose. Now how am I supposed to handle that?
Here is working solution (You may want to improve it):
<asp:FormView ID="FormView1" runat="server" DataSourceID="ObjectDataSource1"
AllowPaging="true" OnItemDeleted="FormView1_ItemDeleted" ondatabound="FormView1_DataBound" >
<ItemTemplate>
Key:
<asp:Label ID="KeyLabel" runat="server" Text='<%# Bind("Key") %>' />
<br />
Value:
<asp:Label ID="ValueLabel" runat="server" Text='<%# Bind("Value") %>' />
<br />
<asp:Button ID="DeleteButton" runat="server" CausesValidation="False" CommandName="Delete"
Text="Delete" />
<hr />
<asp:Label ID="Label1" runat="server" Text="does not work"></asp:Label>
</ItemTemplate>
</asp:FormView>
<asp:ObjectDataSource ID="ObjectDataSource1" runat="server" SelectMethod="GetList"
DeleteMethod="Delete" TypeName="MyProject.Repository">
<DeleteParameters>
<asp:Parameter Name="key" Type="Int32" />
</DeleteParameters>
</asp:ObjectDataSource>
codebehind:
public string MyProperty { get; set; }
protected void FormView1_DataBound(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(MyProperty))
{
Label l = FormView1.FindControl("Label1") as Label;
l.Text = "it works. " + MyProperty;
MyProperty = null;
}
}
protected void FormView1_ItemDeleted(object sender, FormViewDeletedEventArgs e)
{
if (e.Exception != null)
{
MyProperty = e.Exception.Message;
e.ExceptionHandled = true;
}
}
Well, one way is to add another public field to the data source object called "Error", then in MyFormViewItemDeleted
change the proper value and re-bind the FormView.
As far as I can see it should work, though there might be easier/more simple way.
Here is how I did after modifying the code a bit. In the code behind, declared a Field in the Class: private string str_feedbackmsg;
try
{
cnn.Open();
SqlCommand cmd = new SqlCommand(dbcmd, cnn);
cmd.ExecuteNonQuery();
str_feedbackmsg = "Database Work Done!";
}
catch (SqlException err)
{
str_feedbackmsg = "Database Error: Please Notify the Site Administrators.";
}
finally
{
cnn.Close();
}
Then in the Databound event for the FormView:
protected void gv_main_DataBound(object sender, EventArgs e)
{
if (IsPostBack)
{
Label l = fv_main.FindControl("lbl_feedback") as Label;
l.Text = str_feedbackmsg;
}
}
精彩评论