Condividi tramite


Persistenza delle modifiche del client in un controllo non di form

È possibile utilizzare ECMAScript del client (JScript, JavaScript) per tenere traccia delle modifiche dello stato del client in un controllo che non è un elemento del form. Tale controllo non dispone di una modalità per eseguire il postback dei dati al server tramite l'invio di form. È possibile eseguire il postback di un evento, tuttavia potrebbe non essere essenziale. È possibile risolvere questo problema se si utilizzano i campi di input nascosti che contengono i dati del controllo. Il controllo deve generare i campi di input nascosti e lo script che inserisce le informazioni sullo stato nei campi nascosti in un determinato momento prima dell'invio del form. Quando il controllo è stato caricato, può recuperare i dati dai campi nascosti e utilizzarli. Per attivare questo meccanismo, un controllo può richiamare il metodo RegisterHiddenField di Page per generare un campo nascosto e implementare l'interfaccia IPostBackDataHandler. In tal modo è possibile recuperare il valore del campo nascosto e aggiornare le proprietà.

Nell'esempio seguente viene mostrato questo scenario. Il controllo nell'esempio (DHtmlControl) genera uno span i cui colori cambiano nel client quando viene selezionato. Il controllo genera una variabile nascosta il cui valore viene impostato su una variabile booleana dallo script del client per indicare se il controllo è stato selezionato. Il controllo espone la proprietà booleana (Selected) che indica se il controllo è stato selezionato sul client. Il controllo implementa l'interfaccia IPostBackDataHandler, per poter leggere il valore del campo nascosto e aggiornare la proprietà Selected quando la pagina viene rinviata al server. Il controllo espone, inoltre, un evento (SelectedChanged), che viene generato se il controllo viene selezionato nel client.

Per generare l'esempio, vedere le istruzioni in Esempi di controlli server.

using System;
using System.Collections;
using System.Collections.Specialized;
using System.Drawing;
using System.Web;
using System.Web.UI;

namespace CustomControls
{
      public class DHtmlControl : Control, IPostBackDataHandler
      {
            public event EventHandler SelectedChanged;

            public string Text
            {
                  get
                  {
                        object obj = ViewState["Text"];
                        return (obj == null) ? String.Empty : (string)obj;
                  }

                  set
                  {
                        ViewState["Text"] = value;
                  }
            }

            public bool Selected
            {
                  get
                  {
                        object obj = ViewState["Selected"];
                        return (obj == null) ? false : (bool)obj;
                  }

                  set
                  {
                        ViewState["Selected"] = value;
                  }
            }

            protected string HelperID
            {
                  get
                  {
                        return "__" + ClientID + "_State";
                  }
            }

            protected override void OnInit(EventArgs e)
            {
                  base.OnInit(e);

                  if (Page != null)
                  {
                        Page.RegisterRequiresPostBack(this);
                  }
            }

            protected override void OnPreRender(EventArgs e)
            {
                  base.OnPreRender(e);

                  if (Page != null)
                  {
                        Page.RegisterHiddenField(HelperID, Selected.ToString());
                  }
            }

            protected override void Render(HtmlTextWriter writer)
            {
                  string postback = "";
                  if (Page != null)
                  {
                        postback = Page.GetPostBackEventReference(this) + ";";
                  }

                  string click = "onclick=\"var sel=getAttribute('selected'); sel = (sel.toLowerCase() == 'true'); sel=!sel; setAttribute('selected', sel.toString());this.style.backgroundColor=sel?'red':'white';" + HelperID +".value=sel.toString();" + postback + "\"";
                  string style = "style=\"cursor:hand;background-color:" + (Selected ? "red" : "white") + "\"";
                  string selected = "selected=\"" + Selected.ToString() + "\"";
                  writer.Write("<span " + style + " " + click + " " + selected + ">" + Text + "</span>");
            }

            bool IPostBackDataHandler.LoadPostData(string postDataKey, NameValueCollection postCollection)
            {
                  string value = postCollection[HelperID];

                  if (value != null)
                  {
                        bool newValue = (String.Compare(value, "true", true) == 0);
                        bool oldValue = Selected;

                        Selected = newValue;

                        // If there is a change, raise a change event.
                        return (newValue != oldValue);
                  }

                  return false;
            }

            void IPostBackDataHandler.RaisePostDataChangedEvent()
            {
                  // There was a change,  so raise any events.
                  if (SelectedChanged != null)
                  {
                        SelectedChanged(this, EventArgs.Empty);
                  }
            }
      }
}
[Visual Basic]
Option Explicit
Option Strict

Imports System
Imports System.Collections
Imports System.Collections.Specialized
Imports System.Drawing
Imports System.Web
Imports System.Web.UI
Imports Microsoft.VisualBasic

Namespace CustomControls
   Public Class DHtmlControl
      Inherits Control
      Implements IPostBackDataHandler
      Public Event SelectedChanged As EventHandler
      
      Public Property Text() As String
         Get
            Dim obj As Object = ViewState("Text")
            If obj Is Nothing Then
               Return String.Empty
            Else
               Return CStr(obj)
            End If
         End Get
         
         Set
            ViewState("Text") = value
         End Set
      End Property
      
      Public Property Selected() As Boolean
         Get
            Dim obj As Object = ViewState("Selected")
            If obj Is Nothing Then
               Return False
            Else
               Return CBool(obj)
            End If
         End Get
         
         Set
            ViewState("Selected") = value
         End Set
      End Property
      
      Protected ReadOnly Property HelperID() As String
         Get
            Return "__" & ClientID & "_State"
         End Get
      End Property
      
      Protected Overrides Sub OnInit(e As EventArgs)
         MyBase.OnInit(e)
         
         If Not (Page Is Nothing) Then
            Page.RegisterRequiresPostBack(Me)
         End If
      End Sub
      
      Protected Overrides Sub OnPreRender(e As EventArgs)
         MyBase.OnPreRender(e)
         
         If Not (Page Is Nothing) Then
            Page.RegisterHiddenField(HelperID, Selected.ToString())
         End If
      End Sub
      
      Protected Overrides Sub Render(writer As HtmlTextWriter)
         Dim postback As String = ""
         If Not (Page Is Nothing) Then
            postback = Page.GetPostBackEventReference(Me) & ";"
         End If
         
         Dim click As String = "onclick=""var sel=getAttribute('selected'); sel = (sel.toLowerCase() == 'true'); sel=!sel; setAttribute('selected', sel.toString());this.style.backgroundColor=sel?'red':'white';" & HelperID & ".value=sel.toString();" & postback & """"
         Dim style As String = "style=""cursor:hand;background-color:" & IIf(Selected, "red", "white").ToString() & """"
         Dim selectedPiece As String = "selected=""" & Selected.ToString() & """"
         writer.Write(("<span " & style & " " & click & " " & selectedPiece & ">" & Text & "</span>"))
      End Sub 
      
      Function LoadPostData(postDataKey As String, postCollection As NameValueCollection) As Boolean Implements IPostBackDataHandler.LoadPostData
         Dim value As String = postCollection(HelperID)
         
         If Not (value Is Nothing) Then
            Dim newValue As Boolean = String.Compare(value, "true", True) = 0
            Dim oldValue As Boolean = Selected
            
            Selected = newValue
            
            ' If there is a change, raise a change event.
            Return newValue <> oldValue
         End If
         
         Return False
      End Function
      
      Sub RaisePostDataChangedEvent() Implements IPostBackDataHandler.RaisePostDataChangedEvent
         ' There was a change, so raise any events.
         RaiseEvent SelectedChanged(Me, EventArgs.Empty)
      End Sub
   End Class 
End Namespace

Pagina che utilizza il controllo DHTML

La pagina seguente utilizza il controllo DHTML e associa un gestore eventi all'evento SelectedChanged. Si noti che nonostante il controllo si trovi tra tag dei form, non è un elemento dei form e non genera una coppia nome/valore che possa essere rinviata al server.

<%@Register TagPrefix="Custom" NameSpace="CustomControls" Assembly="CustomControls" %>
<script language="C#" runat = "server" >
private void SelectedChangedHandler(object sender, EventArgs e)
{
label.Text = "You selected the DHTML control";
}
</script>
<html>
 <body>  
    <form id="Form1" method="post" runat="server">
       <Custom:DHtmlControl OnSelectedChanged = "SelectedChangedHandler" runat="server" Text="SelectMe" />
       <br>
       <asp:Label id = "label" runat = "server" />
    </form> 
  </body>
</html>
[Visual Basic]
<%@Register TagPrefix="Custom" NameSpace="CustomControls" Assembly="CustomControls" %>
<script language="VB" runat = "server" >
    Private Sub SelectedChangedHandler(sender As Object, e As EventArgs)
       label.Text = "You selected the DHTML control"
    End Sub
</script>
<html>
 <body>  
    <form id="Form1" method="post" runat="server">
       <Custom:DHtmlControl OnSelectedChanged = "SelectedChangedHandler" runat="server" Text="SelectMe" />
       <br>
       <asp:Label id = "label" runat = "server" />
    </form> 
  </body>
</html>

Vedere anche

Generazione di script lato client per il postback