演练:使用 IPersonalizable 实现 Web 部件个性化设置

更新:2007 年 11 月

本演练演示如何通过实现用户控件(视为可个性化的 Web 部件控件)提供用户特定的默认值。

此控件最重要的特性是其可个性化属性存储在非值类型的变量中。在这种情况下,值存储在 BulletedList 控件中。这意味着,系统无法知道用户何时更改列表中的值。本演练演示如何通知系统值已被更改,以便保留这些值供将来使用。如果根据每个用户来创建可自定义的联机窗体,这会很有用。Web 部件个性化设置允许系统识别用户,以便在以后访问站点时可以自动还原用户的默认窗体值。

ms366720.alert_note(zh-cn,VS.90).gif说明:

您在本演练中创建的用户控件不是从 WebPart 类继承的控制;但是,用户控件可以作为 WebPart 控件使用。在本演练过程中,会将用户控件添加到一个 WebPartZoneBase 区域。这样可以允许 ASP.NET 将该用户控件包装在 GenericWebPart 控件中。然后,该用户控件便可以像任何其他的 WebPart 控件一样工作,并且使您可以利用个性化设置。

通过本演练,您将学会如何执行以下任务:

  • 创建具有可个性化的属性的用户控件,这些属性的值可以保存在长期存储中。

  • 显示用户特定的默认值。

  • 在区域中将用户控件作为真正的 WebPart 控件使用。

ms366720.alert_note(zh-cn,VS.90).gif说明:

可以使用 ASP.NET 配置文件开发此类应用程序。但在这种情况下,您将不存储要在整个应用程序中(如在购物车应用程序中)重用的用户相关信息。相反,您将为每个控件逐页保存用户特定的首选项或设置。有关配置文件的更多信息,请参见ASP.NET 配置文件属性概述

先决条件

若要完成本演练,您需要:

  • 已在将承载该站点的计算机上安装和配置的 Internet 信息服务 (IIS)。有关安装和配置 IIS 的更多信息,请参见安装中附带的 IIS 帮助文档,或者参见 Microsoft TechNet 站点(“Internet Information Services 6.0 Technical Resources”(Internet 信息服务 6.0 技术资源))上的联机 IIS 文档。

  • 可识别单个用户的 ASP.NET 网站。如果已经配置了这样的站点,则可以将该站点用作本演练的起始点。否则,请参见 如何:在 IIS 5.0 和 6.0 中创建和配置虚拟目录获取有关创建虚拟目录或站点的更多信息。

  • 已配置的个性化设置提供程序和数据库。Web 部件个性化设置默认情况下是启用的,它使用 SQL 个性化设置提供程序 (SqlPersonalizationProvider) 以及 Microsoft SQL Server Standard Edition (SSE) 存储个性化设置数据。本演练使用 SSE 和默认的 SQL 提供程序。如果安装了 SSE,则不需要进行任何配置。SSE 是作为 Microsoft Visual Studio 2005 安装的可选部分提供的,也可以从 Microsoft.com 免费下载。若要使用 SQL Server 的一个完整版本,必须安装和配置一个 ASP.NET 应用程序服务数据库,并将 SQL 个性化设置提供程序配置为连接到该数据库。有关更多信息,请参见为 SQL Server 创建和配置应用程序服务数据库。还可以创建和配置自定义提供程序来使用其他非 SQL 数据库或存储解决方案。有关更多信息和代码示例,请参见实现成员资格提供程序

创建包含引用类型变量的可个性化的用户控件

在本演练的这一部分中,您将创建一个用户控件,该控件允许您输入网站的友好名称和 URL。单击**“保存”**按钮时,该友好名称会自动添加到 BulletedList 控件中。这些值由 Web 部件个性化设置功能根据每个用户存储。每当用户访问来自另一页或新会话中的控件时,系统都会显示保存的 BulletedList 值。

ms366720.alert_note(zh-cn,VS.90).gif说明:

不需要启用 Web 部件个性化设置;默认情况下已启用它。有关个性化设置的更多信息,请参见 Web 部件个性化设置概述

创建可个性化的用户控件

  1. 在文本编辑器中,创建一个包含用户控件的新文件,将其命名为 UrlList.ascx,并保存在 Web 目录中。实现控件行为的代码包含在单独的文件中,如步骤 4 中所示。

  2. 在新文件中,用所使用的编程语言添加控件指令,如下面的示例所示。

    <%@ Control Language="VB" AutoEventWireup="false"  
    CodeFile="UrlList.ascx.vb" Inherits="WebParts_UrlList" %>
    
    <%@ Control Language="C#" AutoEventWireup="true" 
    CodeFile="UrlList.ascx.cs" Inherits="WebParts_UrlList" %>
    
  3. 在该指令下,添加下列元素来表示控件的用户界面 (UI)。

    <table>
    
    <tr>
        <td> 
            <asp:Label ID="NameLabelID" Text="Name: " runat="server" />
        </td>
        <td>
            <asp:TextBox ID="NameTextBoxID" runat="server" />
        </td>
    </tr>
    
    <tr>
        <td>
            <asp:Label ID="UrlLabelID1" Text="Url:  " runat="server" />
        </td>
        <td>
            <asp:TextBox ID="UrlTextBoxID" runat="server" />
        </td>
    </tr>
    
    <tr>
        <td>
            <asp:Button ID="SaveID" runat="server" 
                OnClick="SaveButton_Click" Text="Save" />
        </td>
        <td>
            <asp:Button ID="ResetID" runat="server" 
                OnClick="ResetButton_Click" Text="Reset" />
        </td>
    </tr>
    
    </table>
    
    <div>
         // This is the complex variable whose status 
         // must be preserved.
        <asp:BulletedList 
            ID="BulletedListID" runat="server"
            DisplayMode="HyperLink"  Target="_blank" />
    
    </div>
    
  4. 创建另一个新文件作为伴随文件,并在其中添加下列代码。下面的示例表示实现前面的 UrlList.ascx 控件行为的伴随文件(UrlList.ascx.vb 或 UrlList.ascx.cs,具体取决于所使用的语言)。此代码分为两部分。一部分包含处理用户输入和页加载事件的代码;另一部分包含实现 IPersonalizable 接口的代码。这将允许保留 BulletedList 值,即用户控件的个性化设置。本示例实现 LoadSaveIsDirty 接口成员。

    ' UrlList.ascx.vb
    Imports System
    Imports System.Collections
    Imports System.Web
    Imports System.Web.UI
    Imports System.Web.UI.WebControls
    Imports System.Web.UI.WebControls.WebParts
    
    Partial Class WebParts_VB_UrlList
        Inherits System.Web.UI.UserControl
        Implements IPersonalizable
    
        Private _userUrls As ArrayList
        Private _listDirty As Boolean
    
        ' This code implements the IPersonalizable members.
    
        Public Overridable ReadOnly Property IsDirty() As Boolean _
        Implements System.Web.UI.WebControls.WebParts.IPersonalizable.IsDirty
    
            Get
                Return _listDirty
            End Get
        End Property
    
    
        Public Overridable Shadows Sub Load(ByVal state As PersonalizationDictionary) _
        Implements System.Web.UI.WebControls.WebParts.IPersonalizable.Load
    
    
            If Not (state Is Nothing) Then
    
                Dim userUrlsEntry As PersonalizationEntry = state("userUrls")
                If Not (userUrlsEntry Is Nothing) Then
                    _userUrls = CType(userUrlsEntry.Value, ArrayList)
                End If
            End If
    
        End Sub 'Load
    
        Public Overridable Sub Save(ByVal state As PersonalizationDictionary) _
          Implements System.Web.UI.WebControls.WebParts.IPersonalizable.Save
    
            If Not (_userUrls Is Nothing) AndAlso _userUrls.Count <> 0 Then
                state("userUrls") = New PersonalizationEntry(_userUrls, _
                PersonalizationScope.User)
            End If
    
        End Sub
    
        ' This code handles the user's input.
        Protected Sub SaveButton_Click(ByVal sender As Object, _
        ByVal e As EventArgs)
    
            Dim name As String = NameTextBoxID.Text.Trim()
            Dim url As String = UrlTextBoxID.Text.Trim()
    
            Dim p As New Pair(name, url)
    
            If _userUrls Is Nothing Then
                _userUrls = New ArrayList()
            End If
            _userUrls.Add(p)
    
            BulletedListID.Items.Add(New ListItem(CStr(p.First), _
            CStr(p.Second)))
    
            _listDirty = True
    
        End Sub 'SaveButton_Click
    
    
        Protected Sub ResetButton_Click(ByVal sender As Object, _
        ByVal e As EventArgs)
    
            _userUrls = New ArrayList()
    
             BulletedListID.Items.Clear()
    
            _listDirty = True
    
        End Sub 'ResetButton_Click 
    
    
        Protected Sub Page_Load(ByVal sender As Object, _
        ByVal e As EventArgs)
            If Not (_userUrls Is Nothing) Then
                BulletedListID.Items.Clear()
                Dim p As Pair
                For Each p In _userUrls
                    BulletedListID.Items.Add(New _
                    ListItem(CStr(p.First), CStr(p.Second)))
                Next p
            End If
    
        End Sub 'Page_Load
    
    End Class
    
    // UrlList.ascx.cs
    using System;
    using System.Collections;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.WebParts;
    
    public partial class WebParts_UrlList : System.Web.UI.UserControl, 
        IPersonalizable
    {
        private ArrayList _userUrls;
        private bool _listDirty;
    
           // This code implements the IPersonalizable members.
    
        public new void Load(PersonalizationDictionary state)
        {
            if (state != null)
            {
    
                PersonalizationEntry userUrlsEntry = state["userUrls"];
                if (userUrlsEntry != null)
                {
                    _userUrls = (ArrayList)userUrlsEntry.Value;
                }
    
            }
        }
    
        public void Save(PersonalizationDictionary state)
        {
    
            if ((_userUrls != null) && (_userUrls.Count != 0))
            {
                state["userUrls"] =
                    new PersonalizationEntry(_userUrls, PersonalizationScope.User);
            }
    
        }
    
        public virtual bool IsDirty
        {
            get
            {
                return _listDirty;
            }
        }
    
           // This code handles the user's input.
    
        protected void Page_Load(object sender, EventArgs e)
        {
            if (_userUrls != null)
            {
                BulletedListID.Items.Clear();
                foreach (Pair p in _userUrls)
                {
                    BulletedListID.Items.Add(
                        new ListItem((string)p.First, (string)p.Second));
                }
            }
    
        }
    
        protected void SaveButton_Click(object sender, EventArgs e)
        {
            string name = NameTextBoxID.Text.Trim();
            string url = UrlTextBoxID.Text.Trim();
    
            Pair p = new Pair(name, url);
    
            if (_userUrls == null)
            {
                _userUrls = new ArrayList();
            }
            _userUrls.Add(p);
    
            BulletedListID.Items.Add(
                    new ListItem((string)p.First, (string)p.Second));
    
            _listDirty = true;
        }
    
    
        protected void ResetButton_Click(object sender, EventArgs e)
        {
    
            _userUrls = new ArrayList();
    
             BulletedListID.Items.Clear();
    
            _listDirty = true;
    
        }
    
    } 
    
  5. 将该文件命名为 UrlList.ascx.vb 或 UrlList.ascx.cs(具体取决于所使用的语言),并保存在网站的根目录中。

    ms366720.alert_security(zh-cn,VS.90).gif安全说明:

    该控件具有一个文本框,用于接受用户输入,这是一个潜在的安全威胁。网页中的用户输入可能会包含具有恶意的客户端脚本。默认情况下,ASP.NET 网页验证用户输入,以确保输入中不包含 HTML 元素或脚本。只要启用了此验证,就不需要显式检查用户输入中的脚本或 HTML 元素。有关更多信息,请参见脚本侵入概述

将用户控件作为 Web 部件控件引用

既然已经创建了一个具有可个性化属性的用户控件,您即可创建一个 Web 窗体页,并将该用户控件作为 Web 部件控件承载。

ms366720.alert_note(zh-cn,VS.90).gif说明:

必须将该控件作为 Web 部件控件承载才能使用个性化设置。

将用户控件作为 Web 部件控件引用

  1. 在文本编辑器中,创建一个新文件。将页声明添加到该文件的开头,如下面的示例所示。

    <%@ page language="VB" %>
    
    <%@ page language="C#" %>
    
  2. 在页声明的下面添加一个声明,引用您之前创建的用户控件,如下面的示例所示。

    <%@ Register tagprefix="UserControl" tagname="UrlList" 
    src="UrlList.ascx" %>
    
    <%@ Register tagprefix="UserControl" tagname="UrlList" 
    src="UrlList.ascx" %>
    
  3. 在控件引用下面,添加下面的基本页结构,将用户控件作为 Web 部件控件承载。

    ms366720.alert_note(zh-cn,VS.90).gif说明:

    为了能够将用户控件作为 Web 部件控件使用,页面中必须包含一个 <asp:webpartmanager> 元素,并且必须接着在 <asp:webpartzone> 元素和 <zonetemplate> 元素中包含该用户控件,如下面的示例所示。

    <html>
    <head runat="server">
        <title>Personalizable User Control</title>
    </head>
    <body>
        <form id="form1" runat="server">
          <asp:WebPartManager ID="mgr" runat="server" />
            <div>
              <asp:WebPartZone ID="WebPartZone1" runat="server">
                <ZoneTemplate>
                  < UserControl:UrlList ID="AccUserID" runat="server"
                    title="URL List WebPart" />  
                </ZoneTemplate>
              </asp:WebPartZone>
            </div>    
        </form>
    </body>
    </html>
    
  4. 将该文件命名为 UrlList.aspx,并保存在用户控件所在的目录中。

    现在,您已经创建了一个可个性化的用户控件,并在 Web 窗体页中将其作为 Web 部件控件引用。

最后的步骤是测试用户控件。

测试可个性化的用户控件

  1. 在浏览器中加载 UrlList.aspx 页。

  2. 在**“名称”“URL”字段中输入值,再单击“保存窗体值”**按钮。

  3. 关闭浏览器。

  4. 在浏览器中再次加载该页。

    您之前输入的值应显示在窗体中。这些值是保存在 BulletedList 控件中的值,当您在浏览器中重新加载该页时,便从数据库中还原了这些值。

  5. 在窗体中输入新值,但不要单击该按钮保存新值。关闭浏览器。

  6. 在浏览器中再次加载页。重新显示在窗体中的值应是您输入并保存到个性化设置属性中的原始值。

后续步骤

本演练演示了创建具有可个性化属性的用户控件的基本任务。您所创建的控件允许您保存特定控件和页面的用户特定设置,并会在用户通过新的浏览器会话重新访问该页时显示这些已保存的设置。对进一步研究的建议包括:

请参见

概念

ASP.NET Web 部件概述

Web 部件个性化设置概述