0

ActivityというWebユーザーコントロールを作成しました。OnActivityDeleteと呼ばれるそのWebユーザーコントロールで公開イベントを定義しました。アクティビティコントロールには削除ボタンがあります。削除ボタンがクリックされると、アクティビティコントロールはOnActivityDeleteイベントを発生させます。このWebユーザーコントロールをリピーターで使用しています。リピーターのアイテムデータバインドイベントのOnActivityDeleteイベントにイベントハンドラーを割り当てます。アクティビティコントロールの削除ボタンをクリックすると、イベントはアクティビティコントロールから発生しますが、コントロールを使用しているページのイベントハンドラーにヒットすることはありません。(デバッガーを使用してコードにステップインし、この動作を確認しました)。

私の疑惑は、この動作は、リピーターをデータソースにバインドするときにイベントハンドラーがコードビハインドに追加されるという事実と関係があるということです。これは、ページがポストバックされていない場合にのみ行います。

aspxページのマークアップでアクティビティコントロールのイベントハンドラーを定義することは可能ですか?もしそうなら、これは私の問題を解決しますか?

そうでない場合は、問題を解決するためにリピーターをバインドし、ページが読み込まれるたびにイベントに接続する必要がありますか(これは機能しますが、テストしたばかりです)、またはイベントを永続化するためのビューステートトリックはありますか?

ページのリピーターのマークアップ:

<asp:Repeater ID="rptrActivites" runat="server" EnableViewState="true">
  <ItemTemplate>
    <div class="activity">
      <crm:Activity ID="activityView" runat="server" Activity="<%#Container.DataItem %>" EnableViewState="true" />
    </div>
  </ItemTemplate>
</asp:Repeater>

ページの背後にあるコード:

  Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

    If Not Page.IsPostBack Then
      GetActivities()
    End If

  End Sub

  Private Sub GetActivities()

    Dim oDS As DataSet

    'Code removed for brevity'

    rptrActivites.DataSource = oDataView
    rptrActivites.DataBind()

  End Sub

  Private Sub rptrActivites_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.RepeaterItemEventArgs) Handles rptrActivites.ItemDataBound

    If e.Item.ItemType = ListItemType.Item Or e.Item.ItemType = ListItemType.AlternatingItem Then
      Dim activityView As Activity = e.Item.FindControl("activityView")
      If activityView IsNot Nothing Then
        AddHandler activityView.OnActivityDelete, AddressOf ActivityDelete
      End If
    End If

  End Sub

  Private Sub ActivityDelete(ByVal sender As Object, ByVal e As ActivityDeleteEventArgs)
    'This never fires'
  End Sub

アクティビティコントロールのマークアップ:

<%@ Control Language="vb" AutoEventWireup="false" CodeBehind="Activity.ascx.vb" Inherits=".Activity" %>
<!-- code removed for brevity's sake -->
<asp:LinkButton ID="btnDelete" runat="server" Text="Delete" />
<!-- code removed for brevity's sake -->

背後にあるアクティビティ制御コード:

Public Event OnActivityDelete(ByVal sender As Object, ByVal e As ActivityDeleteEventArgs)

Private Sub btnDelete_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnDelete.Click
  RaiseEvent OnActivityDelete(Me, New ActivityDeleteEventArgs())
End Sub
4

1 に答える 1

1

あなたはほとんどあなた自身の質問に答えました。ページのライフサイクル中にイベントが発生するためには、サーバーは、クライアントが毎回使用できるすべてのコントロールを一貫して再作成できる必要があります。これは、サーバーがビューステートを最上位にロードしてから、クライアント側で発生した変更を識別する前に、元のコントロールを作成する必要があるためです。変更が識別されると、サーバーは変更を適切なイベントにマップし、必要に応じてそれらを起動します。

コントロールがすべてのページレンダリングで一貫して作成されていないようです。したがって、元のコントロールにアタッチできないため、イベントが失われています。

試してみたいことの1つは、Repeatersデータソースをviewstate/serverプロパティに配置することです。そうすれば、!Page.IsPostBackで一度バインドするデータを高価にフェッチするだけで済み、ページが読み込まれるたびにリピーターを一貫して再バインドできます。これにより、ページは、発生しているイベントの元の制御ソースを識別し、それを添付して、要求を処理できるようになります。

于 2010-06-24T16:51:24.277 に答える