Enable PostBack for a ASP.NET User Control
When I click my "Query" button, my TestID textbox TestIDTxt
retained its value, but both myDatePicker
's are blank without any value.
Question: How do I preserve StartDate.SelectedDate and EndDate.SelectedDate between postbacks?
Solution:
As suggested multiple times, removing ReadOnly="true"
on the DateTxt
kept the text value across postbacks. (Thanks Raj Kaimal!)
I then set the SelectedDate
(Date?) property by Date.Parse
'ing the text value automatically on Page_Load() for that user control see code below.
I never did use the ViewState object directly.
myDatePicker.ascx.vb (FINAL)
Imports System.Globalization
Partial Public Class myDate
Inherits System.Web.UI.UserControl
Public Property SelectedDate() As Date?
Get 'Simply return the date'
Return Me.DateTxt_CalendarExtender.SelectedDate
End Get
Set(ByVal value As Date?)
If value = Nothing Then Exit Property
Me.DateTxt_CalendarExtender.SelectedDate = value
Me.DateTxt.Text = Format(value, Me.DateTxt_CalendarExtender.Format)
End Set
End Property
Public Sub Refresh()
Dim tempDate As Date 'SelectedDate is nullable Date (Date?)'
Dim parseState As Boolean = False
parseState = Date.TryParseExact(DateTxt.Text, _
DateTxt_CalendarExtender.Format, _
DateTimeFormatInfo.CurrentInfo, _
DateTimeStyles.None, tempDate)
If parseState Then 'if successful, set the date'
Me.DateTxt_CalendarExtender.SelectedDate = tempDate
End If
End Sub
Private Sub Page_Load(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles Me.Load
Me.Refresh()
End Sub
End Class
myDatePicker.ascx.vb (ORIGINAL)
Partial Public Class myDate
Inherits System.Web.UI.UserControl
Public Property SelectedDate() As Date?
Get
Dim o As Object = ViewState("SelectedDate")
If o = Nothing Then
Return Nothing
End If
Return Date.Parse(o)
End Get
Set(ByVal value As Date?)
ViewState("SelectedDate") = value
End Set
End Property
End Class
myDatePicker.ascx
<%@ Control Language="vb" CodeBehind="myDatePicker.ascx.vb"
Inherits="Website.myDate" AutoEventWireup="false" %>
<%@ Register assembly="AjaxControlToolkit" namespace="AjaxControlToolkit"
tagprefix="asp" %>
<asp:TextBox ID="DateTxt" runat="server" ReadOnly="True" />
<asp:Image ID="DateImg" runat="server" ImageUrl="~/Calendar_scheduleHS.png"
EnableViewState="True" EnableTheming="True" />
<asp:CalendarExtender ID="DateTxt_CalendarExtender" runat="server" Enabled="True"
TargetControlID="DateTxt" PopupButtonID="DateImg"
DefaultView="Days" Format="ddd MMM dd, yyyy"
EnableViewState="True"/>
Default.aspx
<%@ Page 开发者_如何学JAVALanguage="vb" AutoEventWireup="false" CodeBehind="Default.aspx.vb"
Inherits="Website._Default" EnableEventValidation="false"
EnableViewState="true" %>
<%@ Register TagPrefix="my" TagName="DatePicker" Src="~/myDatePicker.ascx" %>
<%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit"
TagPrefix="ajax" %>
<%@ Register Assembly="..." Namespace="System.Web.UI.WebControls"
TagPrefix="asp" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
...
<body>
<form id="form1" runat="server">
<div class="mainbox">
<div class="query">
Start Date<br />
<my:DatePicker ID="StartDate" runat="server" EnableViewState="True" />
End Date
<br />
<my:DatePicker ID="EndDate" runat="server" EnableViewState="True" />
<br/>
<asp:TextBox ID="TestIdTxt" runat="server" /><br />
<div class="query_buttons">
<asp:Button ID="Button1" runat="server" Text="Query" />
</div>
</div>
<asp:GridView ID="GridView1" ... >
</form>
</body>
</html>
Default.aspx.vb
Imports System.Web.Services
Imports System.Web.Script.Services
Imports AjaxControlToolkit
Protected Sub Page_Load(ByVal sender As Object, _
ByVal e As EventArgs) Handles Me.Load
End Sub
Partial Public Class _Default
Inherits System.Web.UI.Page
Protected Sub Button1_Click(ByVal sender As Object, _
ByVal e As EventArgs) Handles Button1.Click
GridView1.DataBind()
End Sub
End Class
Your textbox is readonly therefore it will not store in viewstate any changes to the text value. This is a security feature to prevent tampering of readonly controls.
First of all, does everything work normally if the readonly attribute is removed?
I want the user-control to be exactly what it was before the postback (in both appearance and value).
if so, can you use css/jquery to make the textbox field appear disabled?
I want the user-control to be exactly what it was before the postback (in both appearance and value).
You might try using ControlState for this.
In your init handler:
protected override void OnInit(EventArgs e)
{
Page.RegisterRequiresControlState(this);
}
Elsewhere in your control:
protected override object SaveControlState()
{
NameValueCollection state = new NameValueCollection();
state.Add("value", this.DateTxt.Text);
return state;
}
protected override void LoadControlState(object savedState)
{
NameValueCollection state = (NameValueCollection)savedState;
this.DateTxt.Text = state["value"].ToString();
}
I adapted this from some code I had laying around, so you may need to tweak a bit for your purposes. The ASP.NET runtime will call those two methods during the page lifecycle to save and restore the value of that textbox for you in a ViewState independent way.
The CalendarExtender doesn't work properly with with readonly textboxes. There is a relatively simple workaround, though it looks a bit dirty and isn't really the webforms way. Try putting this in Page_Load:
DateTxt.Text = Request[DateTxt.UniqueID]
Obviously if you're also populating the textbox from ViewState in some cases you'll need to be mindful of that too.
Set the button's onclick event to an event handler in your code:
<asp:Button ID="Button1" runat="server" Text="Query" OnClick="MyButtonClickEventHandler" />
here is an article that should help
http://msdn.microsoft.com/en-us/library/ms972975.aspx
Basically you need to create an event that causes a postback
In the OnLoad event of your user control you can use the values you saved in your viewstate to populate the control. (not 100% if this VB is correct)
Protected Sub Page_Load(ByVal sender As Object, _
ByVal e As EventArgs) Handles Me.Load
Me.DateTxt_CalendarExtender.(property that sets the date) = Me.SelectedDate
//or Me.DateTxt_CalendarExtender.(property that sets the date picked) = ViewState["SelectedDate"] As Date
End Sub
If I understund your question, You have just to overload UserControl.DataBind in the myDate class.
Look here for better documentation.
If your component is created using inner component like textfield you can do like the following example. So, bind the data entered or modified to the inner component and make sure to track the state, and save/load it every postback.
If you draw your own component make sure to override the DataBinding, cause you have to record what user imput in the viewstate, but is much more complicated.
Example of simple UserControl: WebUserControl1.ascx.vb:
Public Class WebUserControl1
Inherits System.Web.UI.UserControl
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
End Sub
Public Property SelectedText() As String
Get
Return TextBox1.Text
End Get
Set(ByVal value As String)
TextBox1.Text = value
End Set
End Property
Public Overrides Sub DataBind()
MyBase.OnDataBinding(EventArgs.Empty)
' Reset the control's state.
' Controls.Clear()
' Check for HasChildViewState to avoid unnecessary calls to ClearChildViewState.
If HasChildViewState Then
ClearChildViewState()
End If
ChildControlsCreated = True
If Not IsTrackingViewState Then
TrackViewState()
End If
End Sub
Protected Overrides Sub LoadControlState(ByVal savedState As Object)
SelectedText = savedState
End Sub
Protected Overrides Function SaveControlState() As Object
Return SelectedText
End Function
End Class
WebUserControl1.ascx:
<%@ Control Language="vb" AutoEventWireup="true" CodeBehind="WebUserControl1.ascx.vb" Inherits="WebApplication1.WebUserControl1" %>
PIPPO:
<asp:TextBox ID="TextBox1" runat="server" Width="384px"></asp:TextBox>
Default.aspx:
<%@ Register src="WebUserControl1.ascx" tagname="WebUserControl1" tagprefix="uc2" %>
<asp:Content ID="HeaderContent" runat="server" ContentPlaceHolderID="HeadContent">
</asp:Content>
<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
<br />
-----------------------------------<br />
<uc2:WebUserControl1 ID="WebUserControl11" runat="server" SelectedText="aaaa" />
<br />
-----------------------------------<br />
<asp:Button ID="Button1" runat="server" Text="Button" />
<br />
<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
<br />
</asp:Content>
Default.aspx.vb
Public Class _Default
Inherits System.Web.UI.Page
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
DataBindChildren()
End Sub
Protected Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Button1.Click
Label1.Text = WebUserControl11.SelectedText
End Sub
End Class
You should be able to add something like this to your calendar to automatically submit your page when a date is selected:
OnClientDateSelectionChanged="document.getElementById('form1').submit();"
You could replace the JavaScript submit with a specific buttonclick if needed, or call an asp.net postback event.
精彩评论