开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜