ASP.NET服务器控件控件可分为以下几类:
8.WebParts控件
ASP.NET中的Web部件技术提供了一种可以开发出由用户定制和灵活自由的界面的方法。由一个个小零件组成了一个web页,客户端用户可以随意地组合这些零件,添加或删除页面上的零件。要完成这样一个功能要使用WebParts的3个组成部分:最上层的WebParts控件(从Part类中派生,不是一个或一些控件,而是把普通ASP.NET服务器控件,用户控件,自定义服务器控件拖入区域控件中时,这些控件自动成为了WebParts控件)中间层的WebParts结构组件(包括WebPartManager和各种区域控件,他们用来管理和协调WebParts控件)最底层的个性化设置(跟用户个性化设置差不多)。
实现WebParts
WebPartManager是一个不可见控件,所有WebParts控件都要依赖于它,所以首先要添加它,并且要位于所有其他WebParts控件的前面。再添加WebPartZone(是一种区域控件,用来包含WebParts控件,一个页面可以放好多WebPartZone控件,把普通ASP.NET服务器控件,用户控件,自定义服务器控件拖入WebPartZone区域控件中时(这些控件必须位于WebPartZone的<ZoneTemplate>属性内(在设计界面拖动时自动加入该属性)),这些控件自动成为了WebParts控件(WebPart类,就可以用WebPart类的属性了,如title标题属性(webpart控件标题)等,需手动添加
,对于多个服务器控件最好将它们置于用户控件里再添加)。如果在页面运行时要添加或删除或编辑WebPartZone区域控件可拖入CatalogZone区域控件(默认情况下不做任何工作,但在其里再拖入1.PageCatalogPart控件后将用多选框列出当前页面上已删除的WebPart控件的标题用下拉列表框显示所有WebPartZone的标题(在WebPartZone的HeaderText属性里设置)可以将选中的WebPart控件的标题添加到任意WebPartZone区域中,在其里拖入2.DeclarativeCatalogePart控件后对于一些不会显示在webpartzone里的控件可以将其拖到
DeclarativeCatalogePart控件的模板里(智能任务栏里的编辑模板)之后就可以在页面中选中该控件向webpartzone添加该控件了并且同一个控件可添加在多个webpartzone中,在其里拖入3.ImportCatalogPart控件后将允许为页面导入.webpart文件)这仨CatalogPart可以拖入同一个CatalogZone区域控件内)。这时运行页面会发现CatalogZone区域控件一片空白,这是因为还没有设置WebPartManager的DisplayMode属性(只能在后置代码里设置,可以在Page_Load事件里给其赋值):
protected void Page_Load(object sender, EventArgs e)
{
WebPartManager1.DisplayMode = WebPartManager.CatalogDisplayMode;(CatalogZone区域控件中 的那仨CatalogPart需要在此模式下工作)
}
其他DisplayMode属性值及其说明:BrowseDisplayMode(默认模式,普通显示模式,不能编辑)
DesignDisplayMode(设计模式,经过身份验证(web.config中默认的身份验证是windows身份验证,而登录控件是依赖Forms身份验证通过membership api来查询用户的,在windows身份验证下登录控件也能用但是以本机用户身份登录进去的)的用户才能拖动webpart更改页面布局,所以我们要配置membership(开启Forms身份验证的话,如果是windows身份验证只能本机登录页面自然不用配置membership),之前已经讲过,但那是将ASPNETDB.MDF加到自己数据库中,由于改了数据库,需要在web.config中配置成员提供者的connectionStringName属性当然那时完全重新写了一个成员提供者,这里我们直接只是开启Form验证就行了,使用默认的成员提供者AspNetSqlMembershipProvider及数据库ASPNETDB.MDF就可以了,然后利用登录控件登录)
补:对于SQLServer数据库文件(如ASPNETDB.MDF等没有被附加到SQLServer数据库的数据库文件)也能通过数据库连接字符串与之相连,只不过在数据源中选Microsoft SQL Server数据库文件然后浏览,将得到的连接字符串改成:
<add name="ConnectionString" connectionString="Data
Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\Database.mdf;Integrated Security=True;User Instance=True"
providerName="System.Data.SqlClient"/> |DataDirectory| 应该是指应用程序默认数据库文件夹吧,如:App_Data目录,对SQL数据库文件(SQL数据库也适应)的查询,只要在服务器资源管理器的数据库上右键选新建查询即可。
EditDispalyMode(编辑模式,1.AppearanceEditorPart(自定义webpart的视觉属性如宽高),2.BehaviorEditorPart(自定义webpart的行为属性如最小化关闭编辑按钮(只有在共享个性化的设置下才会显示(下面会讲)),3.LayoutEditorPart(自定义webpart的布局属性如选择最小化或正常状态或设置控件将出现在目标区域中的位置的索引),4.PropertyEditorPart(编辑已声明webpart控件的一部分的自定义属性)这四个EditorPart需要在此模式下工作,可以单击每个webpart的编辑来设置)
ConnectDisplayMode(通信模式,允许个webpart间进行通信)
以上5种模式除BrowseDisplayMode模式外,都可以设置webpart,所以ASP.NET默认将保存用户(就是通过身份验证的用户,无论是windows还是Forms身份验证)的个性化设置(WebPartManager的PersonaliZation默认为true)到ASPNETDE.MDF里,同一用户设置完webpart后下次登录进来看到的界面将是上次设计的界面,但对于匿名用户则无法保存个性化信息甚至无法访问本页(webpart个性化不像用户个性化那样通过修改<anonymousIdentification enabled="true"/>就可以允许个性化信息的匿名保存)
接下来我们来设置WebPartZone控件的样式。WebPartZone的WebPartVerbRenderMode属性有俩值Menu(webpart的谓词存在于菜单中,此时可以设置以Menu开头的Style属性)TitleBar(webpart的谓词以链接的形式存在,这时可以设置以TitleBar开头的Style属性)。而对于每种谓词都可以对其设置样式:
ConnectVerb(链接按钮)CloseVerb(关闭按钮)DeleteVerb(删除按钮)EditVerb(编辑按钮)ExpoertVerb(导出按钮)HelpVerb(帮助按钮)MinimizeVerb(最小化按钮)RestoreVerb(恢复按钮)
partstyle(用于设置其内部的webpart的样式,其中有一个HorizontalAlign(设置webpart的对齐方式很有用))
LayoutOrientation(webpartzone内webpart的显示的排列方式)
EmptyZone(当内部没有webpart时显示的文字)
最好不要给webpartzone设置宽和高,因为这样即使关闭其内的webpart,webpartzone还是那么大。
对于那些webpart控件尤其是用户控件,最好在设计用户控件之前就把用户控件里的控件样式设计好,当然也可以现在去用户控件那里改。
在用户控件里给某一控件定义好cssclass,然后再到webpart页css此类,最后再到partstyle里的cssclass运用此类是很好的方法。
前面已经说过WebPartManager的Personallization属性默认为true,webpart在非普通模式下就为通过验证的用户提供webpart个性化设置。但我们要改变默认的ASPNETDB.MDF数据库时,因为连接字符串要改变,所以我们也要从新配置一下webpart个性化提供者(ASP.NET默认的个性化提供者是AspNetSqlPersonlizationProvider)。改变数据库的方法就不说了,现在说一下怎么在跟web.config里配置webpart个性化提供者:
<system.web>
<webParts>
<personalization defaultProvider="MyFirstSqlPersonlizationProvider">
<providers>
<clear/>
<add name="MyFirstSqlPersonlizationProvider"
type="System.Web.UI.WebControls.WebParts.SqlPersonalizationProvider" connectionStringName="连接字符串的name"/>
</providers>
</personalization>
</webParts>
</system.web>
跟membership成员提供者及Profile成员个性化提供者的设置差不多,完成后,验证用户的webpart个性化信息存储在
aspnet_PersonlizationPerUser表(用户个性化)aspnet_PersonlizationAllUser表(共享个性化)。
个性化范围设置
之前看了aspnet_PersonlizationPerUser表(用户个性化)aspnet_PersonlizationAllUser表(共享个性化)这两个表
。用户个性化表中存储的webpart个性化设置只对当前用户起作用,而共享个性化表中存储的webpart个性化设置对
所有在web.config中设置了verbs="enterSharedScope"的用户或角色都起作用(可在web.config中指定哪些用户或
角色拥有将webpart个性化设置存储在共享个性化表中的权利,则他设置的webpart个性化也能对其他被指定为拥有
将webpart个性化设置存储在共享个性化表的用户起作用)默认情况下webpartmanager的InitialScope属性值是user
就是用户个性化,还有一个值是shared就是共享个性化(当将其设为shared,那么那些被指定为拥有将webpart个性化
设置存储在共享个性化表的用户或角色们只要一个改变了webpart个性化其他人也会跟着改变,如果将值设为user那
么即使在web.congfig中指定了那些用户,那些用户也不会共有webpart个性化设置,所以可以在编程中设置让那些用
户选择是否将接下来的webpart个性化设置保存到共享个性化表中,这样做更为人性化,呵呵,由于这样一来那些用户
就有了两套webpwrt个性化设置(分别位于两个表中)所以当webpartmanager的InitialScope属性值是user时这些用
户就从aspnet_PersonlizationPerUser表中读取设置,当webpartmanager的InitialScope属性值是shared时这些用
户就从aspnet_PersonlizationAllUser表中读取设置)
在web.config中指定那些用户啊或角色拥有将webpart个性化设置存储在aspnet_PersonlizationAllUser表中的可
能: <system.web>
<webParts>
<personalization>
<authorization>
<allow verbs="enterSharedScope" users="wan" roles="admin"/>
<allow verbs="enterSharedScope" users="feng"/>
</authorization>
</personalization>
</webParts>
</system.web>
可以看出这里并没有改变默认的webpart个性化提供者,自然也没有改变默认的数据库。
编程中设置让那些用户选择是否将接下来的webpart个性化设置保存到共享个性化表中:
先将webpartmanager的InitialScope属性值设为user
public partial class _Default : System.Web.UI.Page { private WebPartManager wbp; protected void Page_Load(object sender, EventArgs e) { string s = DropDownList1.SelectedValue; switch (s) { case "普通模式": WebPartManager1.DisplayMode = WebPartManager.BrowseDisplayMode; break; case "Catalog模式": WebPartManager1.DisplayMode = WebPartManager.CatalogDisplayMode; break; case "设计模式": WebPartManager1.DisplayMode = WebPartManager.DesignDisplayMode; break; case "编辑模式": WebPartManager1.DisplayMode = WebPartManager.EditDisplayMode; break; case "通信模式": WebPartManager1.DisplayMode = WebPartManager.ConnectDisplayMode; break; } //获取当前页的WebPartManager的实例 wbp = WebPartManager.GetCurrentWebPartManager(Page); //如果当前用户被配置为webpart个性化可以共享 if (wbp.Personalization.CanEnterSharedScope) { Panel1.Visible = true; //Panel1里是供该用户是否共享其个性化设置的选择 //wbp.Personalization.Scope 获取当前webpartmanager的InitialScope属性值的设置 if (wbp.Personalization.Scope == PersonalizationScope.Shared) { RadioButton1.Checked = true; } else { RadioButton2.Checked = true; } } } protected void RadioButton1_CheckedChanged(object sender, EventArgs e) { //选中了是共享 //wbp.Personalization.Scope 获取当前设置,对应webpartmanager的InitialScope属性值 //PersonalizationScope.User对应webpartmanager的InitialScope属性值User if (wbp.Personalization.Scope==PersonalizationScope.User) { wbp.Personalization.ToggleScope(); //在User与Shared间切换 } } protected void RadioButton2_CheckedChanged(object sender, EventArgs e) { //选中了不共享 if (wbp.Personalization.Scope == PersonalizationScope.Shared) { wbp.Personalization.ToggleScope(); //在User与Shared间切换 } } protected void LinkButton1_Click(object sender, EventArgs e) { wbp.Personalization.ResetPersonalizationState(); 重置刚刚操作的个性化设置 } }
个性化WebPart属性
有时候用户希望保存某个控件(当然这个控件必须位于webpartzone中即必须是webpart控件)的某个属性值,在下一 次访问时仍然能看到上次对该控件的某个属性值的操作。这就用到了个性化WebPart属性(通过在用户控件的后置代码里写一个级别为[Personalizable]的属性(这种属性的值能在页面回发时被保存到webpart个性化表中(具体是那 两个表的哪一个,看你设的user还是shared了)要强调的是在共享个性化模式下该属性既可以保存在共享个性化表里 也可以保存在个人个性化表里(个人个性化表里的属性值要在个人个性化模式下更改了)),当然也可以直接在本页的 后置代码中写(如果你的webpart控件没放在用户控件里)把要保存的该控件的属性写在get与set里。另外如果在页 面添加的控件的ID和用户控件里的同样的控件ID相同不要奇怪,因为其实它们的ID传到客户端是不相同的,因为位于 容器(如panel,用户控件等)里的控件的ID会添加上其父容器的ID作为前缀。 在用户控件的后置代码里写个性化WebPart属性的代码: [Personalizable]
public string textvalue
{
get { return TextBox1.Text; }
set { TextBox1.Text = value; }
} 这里保存的是TextBox1的Text属性值。
在webpart页的后置代码里写个性化WebPart属性的代码(如果你的webpart控件放在用户控件Usercon1里): [Personalizable]
public string textvalue
{
get { return ((TextBox)Usercon1.FindControl("TextBox1")).Text; }
set { ((TextBox)Usercon1.FindControl("TextBox1")).Text = value; }
}
很奇怪这样不能保存该属性值,难道在webpart页的后置代码里写个性化WebPart属性的代码, webpart控件不能放在用户控件里?
最后在用户控件里的控件其实在其他容器里有时也会出现这种现象,你如果想给其里面的控件添加事件,发现在该控件的属性边框里没有事件闪电,这时可以手工在用户控件或其他容器的前置代码和后置代码里分别添加。
webpart控件之间的通讯
webpart控件之间的通信机制我们可以实现基于静态连接和动态连接的WebPart通信。
在互相通信的WebPart控件之间,一方作为Provider,另一方作为Consumer,他们之间的数据交互由WebPartManager来管理。在同一个页面中,可以存在多对通信,同一个Provider可以与多个Consumer通信,但是一个Consumer只能从一个
Provider那获取数据。
实现WebPart通信的方法:
(1)定义接口
(2)实现接口成员
(3)在Provider中实现[ConnectionProvider]方法
(4)在Consumer中实现[ConnectionConsumer]方法
(5)在WebPartManager中声明静态连接(如果是静态连接)
原理:Provider实现接口并且在[ConnectionProvider]级别的方法中向WebPartManager提供该接口,WebPartManager向Consumer的[ConnectionConsumer]级别的方法中输送该接口,Provider与Consumer就通过该接口通讯。
基于动态的连接的WebPart通信只是不需要在WebPartManager中声明静态连接,并且添加了一ConnectionsZone。
本例要实现有日历控件的webpart控件(Provider)与有文本框控件的webpart控件(Consumer)之间的通讯:
在website无法直接添加接口文件,可以直接添加一个类文件,然后将其改成接口文件即可:
public interface myinterface
{
DateTime GetTime(); //只定义了一个方法
}
日历控件所在的用户控件作为接口提供者,首先要实现接口,并且有一个[ConnectionProvider]级别的方法:
public partial class Calendar : System.Web.UI.UserControl,myfirstinterface//继承接口
{
DateTime dt;
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Calendar1_SelectionChanged(object sender, EventArgs e)
{
dt = Calendar1.SelectedDate;
}
[ConnectionProvider("myfirstinterface", "myProvider")]
public myfirstinterface theinterface() //[ConnectionProvider]方法,第一个参数是接口,第
{ 二个参数不知道是啥,不过静态链接的话要在
return this; webpartmanager里ProviderConnectionPointID
} 里指出来,下面也是一样。
public DateTime GetTime() //实现接口方法
{
return dt;
}
}
文本框所在的用户控件作为接口接收者,要有一个[ConnectionProvider]级别的方法,在该方法里得到接口完成通讯:
public partial class Formuc : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
}
[ConnectionConsumer("myfirstinterface", "myConsumer")]
public void consumer(myfirstinterface theinterface) //[ConnectionConsumer]方法
{
TextBox1.Text = theinterface.GetTime().ToString(); 得到接口,就可以访问接口的成员了
} 而在此例中接口的GetTime()已在Calendar里实现了
}
如果是静态链接,还要在WebPartManager里:
<asp:WebPartManager ID="wpManager" runat="server">
<StaticConnections>
<asp:WebPartConnection ID="myConnection"
提供者id ProviderID="Calendar1" ProviderConnectionPointID="myProvider"
接收者id ConsumerID="Formuc1" ConsumerConnectionPointID="myConsumer">
</asp:WebPartConnection>
</StaticConnections>
</asp:WebPartManager>
动态链接除了加ConnectionsZone,还要将WebPartManager的 DisplayMode 设置为
WebPartManager.ConnectDisplayMode;而动态链接则不要如此设置。(本人动态链接没实现,有谁知道请留言!)
webpart使用:http://www.cnblogs.com/hide0511/archive/2006/11/05/551020.html
http://jackyrong.cnblogs.com/archive/2005/10/28/263538.html
http://www.cnblogs.com/happyhippy/archive/2007/04/13/712399.html
http://zmsx.cnblogs.com/archive/2005/12/21/301994.html (通讯)
http://blog.csdn.net/xuwenwu/archive/2007/01/17/1485519.aspx (综合)