webpart自定义属性的persist

开始之前先将一般自定义wp属性的用法列下来:

    [Personalizable(PersonalizationScope.Shared),Webpartstorage(Storage.Share)]
   Public string ConnectionString()

  {
}

这里就将这两个属性的意思从msdn摘抄一下

PersonalizationScope Enumeration

User

When referring to the scope associated with a Web Parts control property, User scope indicates that the property can only load and store data applicable to all users when running on a page in Shared scope. However, when the property's control is running on a page in User scope, the property's per-user and all-user data will be loaded and merged. In this case, though, only per-user data will be saved when a page is running in User scope.

当涉及与一个 Web 部件控件属性相关联的范围时,User 范围表明该属性只能加载和保存在 Shared 范围内的页面上运行时适用于所有用户的数据。然而,当属性控件运行于 User 范围内的页面上时,属性的单个用户数据和所有用户数据都将会被加载和合并。这种情况下,当页面在 User 范围内运行时,只有单个用户数据才会被保存。

Shared

When referring to the scope associated with a Web Parts control property, Shared scope indicates that the property normally only allows loading or saving of data associated with all users.

当表示与一个 Web 部件控件属性相关联的范围时,Shared 范围指示该属性通常只允许加载或保存与所有用户关联的数据。

Storage Enumeration

None
The property will not be stored. 

Personal
The property will be stored on a per user basis. 

Shared
The property will be stored with the same value for all users. Typically only the administrator can set this property. 

最后再转一篇实例文章http://zhangxx.bfor.cn/archive/125938.aspx

 

Web Part 框架都会自动保存个性化数据,缺省范围是用户范围。换句话说,每个用户都有自己的个性化属性,当然也可以创建可供共享的用户范围。
我们在这里分析一个webpart实例。具体就是一旦你输入了sql命令,它将显示数据库数据。
DataPart Web Part包括一个用户范围的个性化属性--SelectCommand,一个共享属性--ConnectionString。

Listing 1. DataPart.ascx
<%@ Control Language="VB" ClassName="DataPart" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>
<script runat="server">

    Private _connectionString As String =  String.Empty
    Private _selectCommand As String =  String.Empty

    <Personalizable(PersonalizationScope.Shared)> _
    <WebBrowsable> _
    Public Property ConnectionString() As String
        Get
                 Return _connectionString
        End Get
        Set (ByVal Value As String)
                 _connectionString = value
        End Set
    End Property

    <Personalizable> _
    <WebBrowsable> _
    Public Property SelectCommand() As String
        Get
                 Return _selectCommand
        End Get
        Set (ByVal Value As String)
                 _selectCommand = value
        End Set
    End Property

    Private  Sub Page_PreRender()
        If _connectionString <> String.Empty And_selectCommand <> String.Empty Then
            Try
                Dim dad As SqlDataAdapter =  New SqlDataAdapter(_selectCommand
,_connectionString)
                Dim dst As DataSet =  New DataSet()
                dad.Fill(dst)
                grdData.DataSource = dst
                grdData.DataBind()
            Catch e As Exception
                lblError.Text = e.Message
            End Try
        End If
    End Sub

</script>

<asp:Label
    id="lblError"
    EnableViewState="false"
    Runat="server" />

<asp:GridView
    id="grdData"
    Runat="server" />

注意: ConnectionString为共享范围。只能由管理员在共享模式下编辑。
selectCommand 为用户范围,可在用户范围或者共享范围编辑。共享模式下编辑实际上是为每个人提供缺省值(即覆盖缺省值)。
实例中有Personalization Manager,可切换范围。

Listing 2. ShowDataPart.aspx
<%@ Page Language="VB" %>
<%@ Register TagPrefix="user" TagName="DataPart" Src="~/DataPart.ascx" %>
<%@ Register TagPrefix="user" TagName="PersonalizationManager"
    Src="~/PersonalizationManager.ascx" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
   "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<script runat="server">

    Protected  Sub Menu1_MenuItemClick(ByVal sender As Object, ByVal e As MenuEventArgs)
        WebPartManager1.DisplayMode = WebPartManager1.DisplayModes(e.Item.Text)
    End Sub
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
    <style type="text/css">
        .personalizationManager
        {
            border:dotted 2px orange;
            padding:5px;
            background-color:White;
            font:12px Arial, Sans-Serif;
        }
        .personalizationManager span
        {
            padding-right:10px;
            margin-right:10px;
            border-right:solid 1px black;
        }
        .personalizationManager a
        {
            text-decoration:none;
        }
        .column
        {
            float:left;
            width:30%;
            height:200px;
            margin-right:10px;
            border:solid 1px black;
            background-color: white;
        }
        .menu
        {
            margin:5px 0px;
        }
        html
        {
            background-color:#eeeeee;
        }
    </style>
    <title>Show Data Part</title>
</head>
<body>
    <form id="form1" runat="server">
    <user:PersonalizationManager
        id="PersonalizationManager1"
        Runat="Server" />

    <asp:WebPartManager
        id="WebPartManager1"
        Runat="server" />

        <asp:Menu
            id="Menu1"
            OnMenuItemClick="Menu1_MenuItemClick"
            Orientation="Horizontal"
            CssClass="menu"
            Runat="server">
            <Items>
            <asp:MenuItem Text="Browse" />
            <asp:MenuItem Text="Design" />
            <asp:MenuItem Text="Edit" />
            </Items>
        </asp:Menu>

        <asp:WebPartZone
            id="WebPartZone1"
            CssClass="column"
            Runat="server">
            <ZoneTemplate>
            <user:DataPart
                id="DataPart1"
                Title="Data Part"
                Description="Displays database records"
                Runat="server" />
            </ZoneTemplate>
        </asp:WebPartZone>

        <asp:WebPartZone
            id="WebPartZone2"
            CssClass="column"
            Runat="server" />

        <asp:EditorZone
            id="EditorZone1"
            CssClass="column"
            Runat="server">
            <ZoneTemplate>
            <asp:PropertyGridEditorPart
                id="PropertyGridEditorPart1"
                Runat="server" />
            </ZoneTemplate>
        </asp:EditorZone>
    </form>
</body>
</html>

connection string  可以如下:

Server=.\SQLExpress;Trusted_Connection=true;
AttachDbFileName=|DataDirectory|MyDatabase.mdf;User Instance=true

SQL SELECT statement 可以如下:

SELECT * FROM Movies

运行效果图:

2.复杂的个性化属性

上节的个性化属性仅表示简单的类型如字符串和整数。现在我们再讲解一个可以处理更复杂类型的实例,如数组、自定义类。

该实例使用了ObjectStateFormatter类,这是一个非常有用的类型,用于序列化和非序列化Web Part属性,它可以序列化以静态方式表示的任何类状态。

注意:

复杂的属性构成webpart框架的一个重要局限。webpart框架能够自动侦测简单属性,但不能侦测复杂的属性。即:webpart框架能检测不可变的的属性,无法检测可变的属性,

备注:这里的可变是指实例化后属性的变化。参数就是可变的,值是不可变的。

例如,试图在个性化属性中返回数组表 ,不会出现异常,但也保存不了数组表。原因在于webpart框架无法检测可变的属性。

有两种方法解决该问题。我们在最后专门讲解利用非常实用的IPersonalizable接口去管理个性化,保存可变的webpart属性。
这里我们将先利用一个非常有用的方法,即SetPersonalizationDirty()方法。它包含了共享(static)和一个实例,即可以在从用户控件创建webpart采用,也可以从来自webpart基类的“真实”的Web 部件采用。

下面的实例就是一个以数组方式创建和保存的任务列表

Listing 3. FirstTaskListPart.ascx
<%@ Control Language="VB" ClassName="FirstTaskListPart" %>
<script runat="server">

    Private _tasks As ArrayList = Nothing

    <Personalizable()> _
    Public Property Tasks() As ArrayList
        Get
            Return _tasks
        End Get
        Set(ByVal Value As ArrayList)
            _tasks = value
        End Set
    End Property

    Private Sub Page_PreRender()
        grdTasks.DataSource = _tasks
        grdTasks.DataBind()
    End Sub

    Protected Sub btnAdd_Click(ByVal sender As Object, ByVal e As EventArgs)
        If _tasks Is Nothing Then
            _tasks = New ArrayList()
        End If
        _tasks.Add(txtNewTask.Text)
        WebPart.SetPersonalizationDirty(Me)
    End Sub
</script>

<asp:GridView
    id="grdTasks"
    Runat="server" />

<hr>
<b>New Task:</b>
<asp:TextBox
    id="txtNewTask"
    Runat="server" />
<asp:Button
    id="btnAdd"
    Text="Add"
    OnClick="btnAdd_Click"
    Runat="server" />

注意:当新项目加进数组以后,调用WebPart.SetPersonalizationDirty()方法否则不能增加更多项目。另外_tasks初始值设为Nothing (null)。
Private _tasks As ArrayList = Nothing

一般认为首先赋予的个性化属性为缺省值。webpart框架将比较当前值和缺省值,如没有变化,不保存个性化数据。

假如初始化值如下
Private _tasks As ArrayList = New ArrayList()
当加进新项目,如果ArrayList 是参数型,webpart框架无法检测到变化(由WebPart.SetPersonalizationDirty()方法告知框架已经发生变化)。

3.使用IPersonalizable接口

大多数情况下使用Personalizable属性(attribute)就能够自动保存自定义webpart属性(properties)。
然而Personalizable 属性(attribute)有下面的局限性。

1。 Personalizable 属性(property)必须是公共的。
2.  Personalizable 属性(property)必须具有公共的读写访问。
3.  Personalizable 属性(property) 不能索引和参数。
4. Personalizable 属性(property)不能出现在递归控件。

实现IPersonalizable 接口可以克服上述局限来保存需要的数据。
IPersonalizable 接口成员包括一个属性,两个方法:

IsDirty属性--webpart框架调用Save()方法时返回TRue,视为“已更新”。

Load()方法--加载个性化状态信息
Save()方法--保存性化状态信息
下面的SecondTaskListPart.ascx展示了在webpart任务表中如何应用IPersonalizable接口。

Listing 4. SecondTaskListPart.ascx
<%@ Control Language="VB" ClassName="SecondTaskListPart" %>
<%@ Implements Interface="System.Web.UI.WebControls.WebParts.IPersonalizable" %>
<script runat="server">

    Private _tasks As ArrayList = New ArrayList()
    Private _isDirty As Boolean = False

    Public Property Tasks() As ArrayList
        Get
            Return _tasks
        End Get
        Set(ByVal Value As ArrayList)
            _tasks = value
        End Set
    End Property

    Public ReadOnly Property IsDirty() As Boolean Implements IPersonalizable.IsDirty
        Get
            Return _isDirty
        End Get
    End Property

    Public Sub Save(ByVal state As PersonalizationDictionary) Implements IPersonalizable.Save
        Dim wpm As WebPartManager = WebPartManager.GetCurrentWebPartManager(Page)
        state.Add("tasks", New PersonalizationEntry(_tasks, wpm.Personalization.Scope))
    End Sub

    Public Sub Load(ByVal state As PersonalizationDictionary) Implements IPersonalizable.Load
        _tasks = CType(state("tasks").Value, ArrayList)
    End Sub

    Private Sub Page_PreRender()
        grdTasks.DataSource = _tasks
        grdTasks.DataBind()
    End Sub

    Protected Sub btnAdd_Click(ByVal sender As Object, ByVal e As EventArgs)
        _tasks.Add(txtNewTask.Text)
        _isDirty = True
    End Sub
</script>
<asp:GridView
    id="grdTasks"
    Runat="server" />

<hr>
<b>New Task:</b>
<asp:TextBox
    id="txtNewTask"
    Runat="server" />
<asp:Button
    id="btnAdd"
    Text="Add"
    OnClick="btnAdd_Click"
    Runat="server" />

上面代码直接<%@ Implements %>直接实行IPersonalizable接口。
body部分包含GridView,TextBox,Button控件。用户在TextBox输入描述,点击按钮执行btnAdd_Click(),增加新任务到数组列表,同时将Web Part标为dirty。

页面每次加载webpart,调用Load()方法,从个性化数据库中返回任务列表。当用户输入新任务,webpart被标为dirty,同时调用Save() 方法。

注意:

Load() 和 Save()都使用了包PersonalizationEntry类实例的PersonalizationDictionary。每个PersonalizationEntry表示正要保存的信息和个性化范围(User 和 Shared)。在Save()方法中,采用WebPartManager控件去检测页面当前的个性化范围。

posted @ 2009-12-28 23:29  彷徨......  阅读(662)  评论(0编辑  收藏  举报