欢迎您访问我爱IT技术网,今天小编为你分享的编程技术是:【一个“简单”的ASP.NET的服务器控件】,下面是详细的分享!
一个“简单”的ASP.NET的服务器控件
以下为引用的内容:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Design;
using System.IO;
using System.Text;
using System.Web;
using System.Web.Caching;
using System.Web.UI;
using System.Web.UI.WebControls;
[assembly: TagPrefix("EndWell", "EW")]
namespace EndWell
{
[DefaultProperty("Text")]
[ToolboxData("<{0}:HyperlinkFileList runat="server">")]
[ToolboxBitmap("HyperlinkFileList.ico")]
public class HyperlinkFileList : Panel
{
[Bindable(true)]
[Category("Files List")]
[Description("The Title of the list of files")]
public string FilesTitle {get; set;}
[Bindable(true)]
[Category("Files List")]
[Description("The directory of the files to list: (~/Files/)")]
// these two built in editors were lacking:
//[EditorAttribute(typeof(System.Web.UI.Design.UrlEditor), typeof(UITypeEditor))]
//[EditorAttribute(typeof(System.Windows.Forms.Design.FolderNameEditor), typeof(UITypeEditor))]
[EditorAttribute(typeof(EndWell.DualModeFolderEditor), typeof(UITypeEditor))]
public string FilesDirectory { get; set; }
[Bindable(true)]
[Category("Files List")]
[Description("The filter for the files to show: (*.*)")]
public string FilesFilter { get; set; }
[Bindable(true)]
[Category("Files List")]
[Description("Text to show when there are no files")]
public string NoFilesText { get; set; }
// ---- Private vars --------------------------
private String[] m_FilesArray; // cached for performance
// ---- Default constants-------------------
const String DEF_FILES_DIR = "~/xml/";
const String DEF_FILES_FILT = "*.xml";
const String DEF_FILES_TITLE = "XML Files:";
const String DEF_NOFILES_TEXT = "";
// ---- Constructor --------------------------
public HyperlinkFileList()
{
// set defaults for our properties
FilesDirectory = DEF_FILES_DIR;
FilesFilter = DEF_FILES_FILT;
FilesTitle = DEF_FILES_TITLE;
NoFilesText = DEF_NOFILES_TEXT;
// Set defaults for panel properties
// I don't like the default width to be full screen
// And a border looks better
Width = new Unit("300px");
BorderStyle = BorderStyle.Solid;
BorderWidth = 1;
BorderColor = Color.Black;
// If height is set, force scroll bars to keep list
// from spilling over the panel/div boundaries.
if ((Height != null) && (ScrollBars == ScrollBars.None))
ScrollBars = ScrollBars.Auto;
// Allow multiple controls to be placed horizontally
// (normally each div get's its own line)
Style["display"] = "inline-block";
// add spacing outside the control
Style["margin"] = "0.5em";
// add space inside the control
Style["padding-left"] = "0.5em";
Style["padding-right"] = "0.5em";
Style["padding-bottom"] = "0.5em";
// top space usually comes from the title...
if (String.IsNullOrEmpty(FilesTitle) == true)
Style["padding-top"] = "0.5em";
}
// ---- RenderContents ----------------------------
//
// Spit out the HTML
protected override void RenderContents(HtmlTextWriter Output)
{
// output the title if one was set
if (String.IsNullOrEmpty(FilesTitle) == false)
{
Output.Write("<h3> "); // cosmetic spacing
Output.Write(FilesTitle);
Output.Write("</h3>");
}
GetFilesArray();
if (m_FilesArray.Length == 0)
{
Output.Write(HttpUtility.HtmlEncode(NoFilesText));
}
else
{
foreach (String OneFile in m_FilesArray)
{
HyperLink Link = new HyperLink();
Link.NavigateUrl = Path.Combine(FilesDirectory, Path.GetFileName(OneFile));
Link.Text = Path.GetFileNameWithoutExtension(OneFile);
Link.RenderControl(Output);
Output.WriteBreak();
}
}
}
// ---- GetFilesArray -------------------------
//
// Fill the m_FilesArray with a list of files
// either from disk or the cache
private void GetFilesArray()
{
// see if the file list is in the cache.
// use directory and filter as unique key
m_FilesArray = Page.Cache[FilesDirectory + FilesFilter] as String[];
if (m_FilesArray != null)
return;
// if no files filter set, use the default one.
if (String.IsNullOrEmpty(FilesFilter))
FilesFilter = DEF_FILES_FILT;
// if no files directory set, use the default one.
if (String.IsNullOrEmpty(FilesDirectory))
FilesDirectory = DEF_FILES_DIR;
// if a virtual path is detected, map to full path
String FullPath;
if (FilesDirectory.StartsWith("~"))
FullPath = Context.Server.MapPath(FilesDirectory);
else
FullPath = FilesDirectory;
// get the files
m_FilesArray = Directory.GetFiles(FullPath, FilesFilter, SearchOption.TopDirectoryOnly);
// put the list in the cache so we don't have to read the disk again
// use a dependency on the directory being read from for auto refreshing
Page.Cache.Insert(FilesDirectory + FilesFilter, // unique key
m_FilesArray, // list of files to store
new CacheDependency(FullPath)); // dependency on directory
}
}
}
注意:
控件名字:
去烦恼一个控件的名称是非常愚蠢做法,真的是这样吗?错误的命名一个控件(或里任何变量)就像结婚。由于你将要与它走很长一段时间,在将来改变它可能会非常痛苦。所以首先要用好你的命名。
我称这个控件为: HyperlinkFileList.
溢出问题:
如果控件的高度一旦设置,文件的列表超出了控件的高度。就会使文件“溢出”控件的边界。
为了解决这个问题,我说下面代码到控件的构造函数之中:
|
以下为引用的内容: if ((Height != null) && (ScrollBars == ScrollBars.None)) |
CSS 布局:
因为控件是基本是一个div(panel渲染成一个div),然后,设置“display”属性为“inline-block”,允许多个控件被并排的一起。
|
以下为引用的内容: Style["display"] = "inline-block"; |
CSS框模型:
我不喜欢文本卡在控件的左侧,所以我添加一些CSS来填充。我也在控件的周围使用一些css样式。使它不会与其它控件贴的很死。
|
以下为引用的内容: // add spacing outside the control Style["margin"] = "0.5em"; // add space inside the control Style["padding-left"] = "0.5em"; |
状态管理:
在最初的测试的时候, 我发现每次控件都能运行,它都将重新读取的文件目录。文件输入输出代价是很昂贵的。我想去结合的服务器控件的“State”。但它使用的是View State 类型,两次发送文件列表到客户端是效率非常低的 。一次作为HTML列表,一次在ViewState 。
所以我想使用 Session State, Application State 和Cache。
我决定将文件列表放在一个缓存对象之中。使列表能在session之间共享。如果内存在溢出,缓存中的列表将会丢失。
我将文件的目录和文件filter连接在一起,作为缓存中索引键。这样允许多个控件同时使用和共享文件列表。
开始,我添加了使开发人员可以强制重新读取需要的文件的功能。但是,缓存对象可以使用依赖关系:任何从属目录更改会导致缓存过期。最后的代码是非常的简单:
|
以下为引用的内容: // put the list in the cache so we don't have to read the disk again |
侧注:当然,这只是一个代码行,但做了几个小时的研究,以决定这是最好的方法去处理状态的管理的问题。有时需要很长的时间编写很少的代码。
Property Editor:
我将所有的自定义属性分组到标题 “Files List”下面。他们都在一个地方与Panel的属性分离开来。

下面是四个控件在一个页面上的标签
|
以下为引用的内容: <EW:HyperlinkFileList ID="HyperlinkFileList5" runat="server" BackColor="#FFFF66" |
下面是他们渲染之后的样子:

第二部分:自定义服务器控件编辑器
选择文件目录:
我认为粘贴文件的目录路径是业余开发人员使用的法子,所以我决定添加一个目录浏览器。
开发服务器控件编辑器所用时间比开发实际控件用的时间更长。
我认为控件的文件的目录,应在两个方面可设置:
Absolute Path: C:\PublicData\ImageFiles\
Virtual Path: ~\xmlFiles\
我试着设计两个内置浏览来设置FilesDirectory属性。
|
以下为引用的内容: [EditorAttribute(typeof(System.Web.UI.Design.UrlEditor), typeof(UITypeEditor))] |
我没有使用UrlEditor,因为它不允许浏览外部站点的主目录。
|
以下为引用的内容: [EditorAttribute(typeof(System.Windows.Forms.Design.FolderNameEditor), typeof(UITypeEditor))] |
我没有使用FolderNameEditor,因为它没有提供虚拟路径的选择。此外,它迫使用户选择一个我不想选择文件。
要创建自定义服务器控件编辑器,就要创建一个类自UITypeEditor继承和覆盖两个功能。..其中一个启动一个DialogBox。
下面是代码:
|
以下为引用的内容: using System; |
以下是编辑的DialogBox,如下所示:

我将不会显示DialogBox代码,因为这是它比较长,涉及广。由于缺乏文档,在开发过程中进行了反复的试错。但也有一些利益的东西。..
目录分隔符(斜线):
反斜杠像 “\~”这样被使用的时候,GetProjectItemFromUrl 函数将不能正常使用。它正斜杠:“/~”能正常工作。因此,我确保所有的目录分隔符使用正斜杠。但是,从目录浏览器返回的目录使用的是反斜杠。所以我们要确保一致性。..虽然它使代码有点凌乱,但真的没有我更喜欢其他选择。
服务器控件开发提示:
一旦控件放置到页面上,你能自动的更新bin文件路径下面的DLL,通过右击右击控件,选择“Refresh”。我不得不删除从bin目录下的控件,然后重新添加到网页上,以获取最新版本到该项目中。
调试编辑器:
调试控件是非常容易的。调试控件的编辑器却非常的难。因为它运行在Visual Studio中。我在不同的地方添加下面代码:
System.Diagnostics.Debugger.Break();
当运行到断点,你得到下面这个令人爽快的画面:

点击 “Debug the program”,将创建一个新的 Visual Studio 实例。你就能够调试控件的编辑器了。原来的运行Visual Studio将锁定的(至少在我这里是这样的),你不得不去终止。由于欠缺自定义服务器控件编辑器的文档,这是非常宝贵的去寻找和了解什么被传递了,发生了什么。
可能的改进:
•标题字体可设置(大小,颜色,背景颜色。..)
•将名称放在一个固定的div中,文件列表在另一可调整大小或有scrollable的div中。
•添加一个布尔字段来选择显示在链接的文件扩展名。
希望这篇文章能够帮助你。
欢迎讨论,谢谢!
参考原文:http://www.codeproject.com/Articles/46264/A-Simple-ASP-NET-Custom-Server-Control.aspx
作者:朱祁林
出处:http://zhuqil.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
以上所分享的是关于一个“简单”的ASP.NET的服务器控件,下面是编辑为你推荐的有价值的用户互动:
相关问题:我用的是Vs2012要用ASP.NET.Web服务器控件做一个登...
答:直接做一个WinForm项目不可以吗? >>详细
相关问题:Asp.Net中,什么是Web控件,Web服务器控件,HTML控...
答:说简单点。Html控件就是Html标签。就是你右击网页-查看源代码。里面看到的比如 >>详细
相关问题:用一个例子讲述如何向ASP.NET Web服务器按钮控件添...
答:编写一个web窗体应用程序,其中当用户单击提交按钮,提示用户你确认提交吗?,当用户单击确定按钮后提交。 1:以声明的方式添加客户端应用程序 >>详细
- 评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)
-
