图 3 从WebPart类继承的类
using System.Web.UI;
using System.Web.UI.WebControls.WebParts;
namespace WingtipWebParts {
public class HelloWorld : WebPart {
public HelloWorld() {
this.Title = "Hello World";
this.TitleIconImageUrl = @"img\WhaleBoy.gif";
}
protected override void RenderContents(HtmlTextWriter writer) {
writer.Write("Can I have your attention please");
}
}
}
图 5 Web部件页面的显示模式
| Display Mode | Description |
|---|
| BrowseDisplayMode | Standard view mode. No personalization or editing. |
| DesignDisplayMode | Enables drag and drop layout personalization or customization. |
| EditDisplayMode | Enables personalization or customization of Web Part properties to change appearance and behavior. Also permits the user to delete Web Parts that have been added to the page dynamically. |
| ConnectDisplayMode | Enables user to connect Web Parts at run time. |
| CatalogDisplayMode | Enables user to add Web Parts into a WebPartZone at run time. |
图 7 自定义个人化属性
public enum Timeframe
{
Today,
Week,
Month
}
...
protected Timeframe _Timeframe = Timeframe.Month;
[Personalizable(PersonalizationScope.Shared),
WebBrowsable, WebDisplayName("Select a news timeframe"),
WebDescription("Use this property to set timeframe")]
public Timeframe Timeframe
{
get { return _Timeframe; } set { _Timeframe = value; }
}
图 8 向页面中添加新的Web部件
<asp:CatalogZone ID="CatalogZone1" runat="server" >
<ZoneTemplate>
<!-- allows users to re-add Web Parts to page after being closed -->
<asp:PageCatalogPart ID="PageCatalogPart1"
runat="server" Title="Local Page Catalog" />
<!-- allows users to add new Web Parts to page -->
<asp:DeclarativeCatalogPart ID="DeclarativeCatalogPart1"
runat="server"
Title="Wingtip Web Parts">
<WebPartsTemplate>
<cc1:WeatherWebPart ID="WeatherWebPart1"
runat="server"
ZipCode="04090" />
</WebPartsTemplate>
</asp:DeclarativeCatalogPart>
</ZoneTemplate>
</asp:CatalogZone>
图 12 动态属性的用户控件
public partial class HelloWorld2 : UserControl, IWebPart {
protected string _title = "My custom user control";
public string Title {
get { return _title; }
set { _title = value; }
}
private string _titleIconImageUrl = "~/img/ALLUSR.GIF";
public string TitleIconImageUrl {
get { return _titleIconImageUrl; }
set { _titleIconImageUrl = value; }
}
private string _catalogIconImageUrl = "~/img/ALLUSR.GIF";
public string CatalogIconImageUrl {
get { return _catalogIconImageUrl; }
set { _catalogIconImageUrl = value; }
}
// Remaining properties not shown...
}
图 13 IWebPart
public class WebPartBase : UserControl, IWebPart {
protected string _title = "[Generic Title]";
public string Title {
get { return _title; }
set { _title = value; }
}
private string _titleIconImageUrl = "~/img/star.GIF";
public string TitleIconImageUrl {
get { return _titleIconImageUrl; }
set { _titleIconImageUrl = value; }
}
private string _catalogIconImageUrl = "~/img/star.GIF";
public string CatalogIconImageUrl {
get { return _catalogIconImageUrl; }
set { _catalogIconImageUrl = value; }
}
// Remaining properties not shown...
}
// Code behind class for CustomerList.ascx User Control
public partial class CustomerList : WebPartBase {
public CustomerList() {
this.Title = "Wingtip Customer List";
this.TitleIconImageUrl = @"~\img\ALLUSR.GIF";
this.CatalogIconImageUrl = @"~\img\ALLUSR.GIF";
}
}
图 14 自定义Web部件还是用户控件
| Feature | WebPart-Inherited Class | User Control |
|---|
| Can be built in separate DLL and installed in the GAC to reuse across applications | Yes | No |
| Can be added to Visual Studio toolbox with a fancy icon | Yes | No |
| Can contained extended verbs | Yes | No |
| Designer support available | No | Yes |
图 15 个人化提供者程序
public abstract class PersonalizationProvider : ProviderBase {
protected abstract void LoadPersonalizationBlobs(
WebPartManager webPartManager,
string path, string userName,
ref byte[] sharedDataBlob,
ref byte[] userDataBlob);
protected abstract void ResetPersonalizationBlob(
WebPartManager webPartManager,
string path,
string userName);
protected abstract void SavePersonalizationBlob(
WebPartManager webPartManager,
string path,
string userName,
byte[] dataBlob);
... // remaining methods not shown
}
图 17 自定义个人化提供者类
namespace Wingtip.Providers {
public class FileBasedPersonalizationProvider : PersonalizationProvider
{
public override string ApplicationName {
get { ... } set { ... }
}
public override void Initialize(
string name, NameValueCollection configSettings) { ... }
public override int GetCountOfState(PersonalizationScope scope,
PersonalizationStateQuery query) { ... }
public override int ResetUserState(string path,
DateTime userInactiveSinceDate) { ... }
protected override void LoadPersonalizationBlobs(
WebPartManager webPartManager, string path,
string userName, ref byte[] sharedDataBlob,
ref byte[] userDataBlob) { ... }
protected override void ResetPersonalizationBlob(
WebPartManager webPartManager, string path,
string userName) { ... }
public override int ResetState(PersonalizationScope scope,
string[] paths, string[] usernames) { ... }
protected override void SavePersonalizationBlob(
WebPartManager webPartManager, string path,
string userName, byte[] dataBlob) { ... }
public override PersonalizationStateInfoCollection FindState(
PersonalizationScope scope,
PersonalizationStateQuery query, int pageIndex,
int pageSize, out int totalRecords) { ... }
}
}
图 18 LoadPersonalizationBlobs方法 和 SavePersonalizationBlob方法
protected override void LoadPersonalizationBlobs(
WebPartManager webPartManager, string path, string userName,
ref byte[] sharedDataBlob, ref byte[] userDataBlob)
{
string fileName = HttpContext.Current.Server.MapPath(
string.IsNullOrEmpty(userName) ?
ConstructAllUsersDataFileName(path) :
ConstructUserDataFileName(userName, path));
if (!File.Exists(fileName)) return;
fileName = string.Intern(fileName);
try
{
// lock on the file name in case two clients try accessing
// the same file concurrently - note we lock on the Interned
// file name string, which will always return the same object
// for identical strings
if (Monitor.TryEnter(fileName, 5000))
{
if (string.IsNullOrEmpty(userName))
sharedDataBlob = File.ReadAllBytes(fileName);
else
userDataBlob = File.ReadAllBytes(fileName);
}
else throw new ApplicationException("Monitor timed out");
}
finally { Monitor.Exit(fileName); }
}
protected override void SavePersonalizationBlob(
WebPartManager webPartManager, string path,
string userName, byte[] dataBlob)
{
string fileName = HttpContext.Current.Server.MapPath(
string.IsNullOrEmpty(userName) ?
ConstructAllUsersDataFileName(path) :
ConstructUserDataFileName(userName, path));
fileName = string.Intern(fileName);
try
{
// lock on the file name in case two clients try accessing
// the same file concurrently
if (Monitor.TryEnter(fileName, 5000))
{
File.WriteAllBytes(HttpContext.Current.Server.MapPath(
fileName), dataBlob);
}
else throw new ApplicationException("Monitor timed out");
}
finally { Monitor.Exit(fileName); }
}
// Helper function for creating a unique file name for all users
// based on a path
private string ConstructAllUsersDataFileName(string path)
{
string fileName =
path.Replace('/', '_').Replace('~', '_').Replace('.', '_');
return "~/App_Data/allusers" + fileName + ".bin";
}
// Helper function for creating a unique file name for a particular
// user based on a path
private string ConstructUserDataFileName(string user, string path)
{
string fileName =
path.Replace('/', '_').Replace('~', '_').Replace('.', '_');
return "~/App_Data/" + user + fileName + ".bin";
}