【问题标题】:Enable PostBack for a ASP.NET User Control为 ASP.NET 用户控件启用 PostBack
【发布时间】:2010-04-30 19:12:40
【问题描述】:

当我点击“查询”按钮时,我的 TestID 文本框 TestIDTxt 保留了它的值,但两个 myDatePicker 都是空白的,没有任何值。

问题:如何在回发之间保留 StartDate.SelectedDate 和 EndDate.SelectedDate?

解决方案: 正如多次建议的那样,删除 DateTxt 上的 ReadOnly="true" 会在回发中保留文本值。 (感谢Raj Kaimal!)

然后,我通过 Date.Parse'在 Page_Load() 上为该用户控件自动设置文本值来设置 SelectedDate(日期?)属性,请参见下面的代码。

我从来没有直接使用过 ViewState 对象。

myDatePicker.ascx.vb(最终版)

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(原始)

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 Language="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

【问题讨论】:

  • 我看不到你在哪里使用用户控件中的任何值,你能显示那部分吗?还是只是您希望 myDatePicker 显示用户在按下 Button1 之前选择的值?
  • 当您说“我如何启用回发”时,您是在问“我如何让我的控件保留它的状态/after/回发”?这可能是其他海报(和我自己)混淆的根源。
  • 是的。我适当地更新了问题。谢谢!
  • 您是在谈论 SelectedDate 保留它的价值(尽管我没有看到任何代码将其设置为任何东西)还是 DateTxt
  • 两者。我希望用户控件与回发之前完全相同(无论是外观还是价值)。

标签: asp.net vb.net user-controls postback


【解决方案1】:

您的文本框是只读的,因此它不会在视图状态中存储对文本值的任何更改。这是一项防止篡改只读控件的安全功能。

首先,如果去掉只读属性,一切正常吗?

我希望用户控件与回发之前完全相同(无论是外观还是价值)。

如果是这样,您可以使用 css/jquery 使文本框字段显示为禁用吗?

【讨论】:

    【解决方案2】:

    我希望用户控件准确无误 回发之前是什么(在 外观和价值)。

    您可以尝试为此使用ControlState

    在您的初始化处理程序中:

    protected override void OnInit(EventArgs e) 
    {
        Page.RegisterRequiresControlState(this);
    }
    

    您可以控制的其他地方:

        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();
        }
    

    我从我放置的一些代码中改编了这个,因此您可能需要根据自己的目的进行一些调整。 ASP.NET 运行时将在页面生命周期中调用这两个方法,以独立于 ViewState 的方式为您保存和恢复该文本框的值。

    【讨论】:

    • 没用。当我提交页面时,用户控件不会保留它们的值并显示为空白。
    【解决方案3】:

    CalendarExtender 不能与只读文本框一起正常工作。有一个相对简单的解决方法,虽然它看起来有点脏并且不是真正的网络表单方式。尝试将其放入 Page_Load:

    DateTxt.Text = Request[DateTxt.UniqueID]
    

    显然,如果您在某些情况下还从 ViewState 填充文本框,您也需要注意这一点。

    【讨论】:

      【解决方案4】:

      将按钮的 onclick 事件设置为代码中的事件处理程序:

      <asp:Button ID="Button1" runat="server" Text="Query" OnClick="MyButtonClickEventHandler" />
      

      【讨论】:

      • 我添加了代码隐藏,显示了 button1 调用的函数。
      • @Steven 但是你在哪里告诉按钮这是它的事件?
      • Protected Sub Button1_Click(...) Handles Button1.Click
      【解决方案5】:

      这是一篇应该有帮助的文章

      http://msdn.microsoft.com/en-us/library/ms972975.aspx

      基本上你需要创建一个导致回发的事件

      【讨论】:

      • 请详细说明。该按钮会导致回发。
      【解决方案6】:

      在用户控件的 OnLoad 事件中,您可以使用保存在视图状态中的值来填充控件。 (如果这个 VB 是正确的,则不是 100%)

      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
      

      【讨论】:

      • 对文本框和img做同样的事情。
      • 它也没有用。此外,在Page_Load() 中,Me.ViewState.Count 的值为零。
      • 在我的网络浏览器中,我选择一个开始和结束日期,输入一个 testid,然后单击“查询”。页面回来了。开始日期为空白。结束日期为空白。 TestID 保留了它的价值。网格视图中的结果仅由 testid 过滤。
      • Page_Load() 中,Me.ViewState.Count 为零。另外,我在浏览器中注意到TestIDTxt&lt;input name="TestIdTxt" type="text" ...&gt;value= 属性中收到了它的值
      • 您何时尝试设置 SelectedDate?我认为您要做的就像@mwilson 一样,或者您需要继承 CalendarExtender 并在其中一个事件期间使用它在 SelectedDate 中放置一个值。
      【解决方案7】:

      如果我理解您的问题,您只需在 myDate 类中重载 UserControl.DataBind。

      查看here 以获得更好的文档。

      如果您的组件是使用像文本字段这样的内部组件创建的,您可以像下面的示例一样进行操作。因此,将输入或修改的数据绑定到内部组件,并确保跟踪状态,并在每次回发时保存/加载它。

      如果您绘制自己的组件,请确保覆盖 DataBinding,因为您必须记录用户在视图状态中输入的内容,但要复杂得多。

      简单的用户控件示例: 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>
      

      默认.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>
      

      默认.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
      

      【讨论】:

      • 数据绑定?什么是数据源?
      • 我希望能理解你的问题,我已经用一个简单的例子编辑了这篇文章。
      【解决方案8】:

      您应该能够将这样的内容添加到您的日历中,以便在选择日期时自动提交您的页面:

      OnClientDateSelectionChanged="document.getElementById('form1').submit();"
      

      如果需要,您可以将 JavaScript 提交替换为特定的按钮点击,或 call an asp.net postback event

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-03-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-09-09
        • 1970-01-01
        相关资源
        最近更新 更多