2007年11月2日

ASP.NET中最漂亮、最酷的弹出对话框

Tomas Petricek著
Highly customizable JavaScript popup control for web page wrapped in ASP.NET custom control.

页面上的弹出对话框

ASP.NET弹出窗口
一个使用javascript编写的,用于在ASP.NET中弹出对话框的用户控件,有渐进颜色,还有能设定弹出时的移动的时间,支持Mozilla, Internet Explorer 和 Opera

image

介绍
这篇文章介绍了一个ASP.NET的窗口弹出控件。该控件模仿MSN 消息警告框的样式,但,它是运行于ASP.NET中的。该窗口的样式可以由用户完全控制,通过设置其颜色或预定义的窗口模式就可修改。该控件还支持窗口拖动,用户可以在窗口上的任一位置移动它。

另 外一个很重要的特性是:该控件适用于多种浏览器。它已经在Microsoft IE,Mozilla Firefox和Opera上进行过测试。但它在不同浏览器上的外观并不完全一样,所以它还不支持filters (filters 仅仅在Microsoft IE最新版中才得到支持。)你可以得到它的HTML属性,因此,可以通过各种属性控制该控件。

以下使用popup代表弹出的对话框控件。

行为事件
该控件有两个事件, LinkClicked (当popup窗口被鼠标点击时的动作) 和PopupClosed (用户单击关闭按钮时的动作)。有三种方式如何处理这些事件。具体使用哪种是由ActionType 决定的。三种行为是:
1,MessageWindow (default) ,在这种情况下,用户控件会打开一个新的浏览窗口,在新的窗口中显示指定在Text 属性中的文字。
2, OpenLink, 在这种情况下,控件允许你做任何 JavaScript 操作或打开链接导任何其它网页 (Link property). 你还可以改变<A>标签内的Target 属性。产生的代码如:<a href="[Link]" target="[LinkTarget]">Link..</a>,因此在链接中小心地使用双引号。(Target 属性只有在 LinkTarget 为空的时候才被加上去)
3,RaiseEvents 当你选择了这种模式,该控件的LinkClicked 或PopupClosed 事件将会被提升到服务器端执行。

image

使用方法
添加这个控件到网页上是很容易的,在Visual studio 开发环境中,你可以仅仅通过在控件工具栏上添加/删除新控件,然后选择本控件的DLL文件。这样,控件就会如普通的按钮、文本框一样,显示在toolbox 中,接下来的使用就是拖到页面上就可以了。

设计
控 件对进一步的设计提供了很丰富的支持,你可以在设计过程中改变它的每一个属性。在Action属性目录下,你可以定义当控件被点击之后的具体动作。在 Texts和Design属性目录中,你可以修改popup对话框的样式和显示的内容。在Behavior属性中,你可以改变控件被显示或隐藏的时间。 AutoShow属性表明是否控件将在页面一被加载的时候就显示。如果你设置DragDrop为true用户还可以改变控件的位置,在页面上拖动该窗口。 如果你把ActionType设置成MessageWindow,你可以通过Window属性目录改变最终显示的消息框的属性。最后一些属性位于 Layout中,它们决定了该窗口的显示位置。


代码
下面的代码描述了如何设置和显示该控件。
Code:
<!-- Popup.aspx -->
<%@ Register TagPrefix="cc1" Namespace="EeekSoft.Web"
  Assembly="EeekSoft.Web.PopupWin" %>

 

Code:
<cc1:popupwin id="popupWin" runat="server" visible="False"
  colorstyle="Blue" width="230px" height="100px" dockmode="BottomLeft"
  windowscroll="False" windowsize="300, 200"></cc1:popupwin>

 

 

// Popup.aspx.cs
// 改变动作类型
popupWin.ActionType=EeekSoft.Web.PopupAction.MessageWindow;
// 设置popup窗口文本
popupWin.Title="This is popup";
popupWin.Message="Message displayed in popup";
popupWin.Text="Text to show in new window..";
// 改变颜色
popupWin.ColorStyle=EeekSoft.Web.PopupColorStyle.Green;
// 改变时间
popupWin.HideAfter=5000;
popupWin.ShowAfter=500;
// 显示类型(页面加载时显示)
popupWin.Visible=true;
 


使用anchor控件
设计
image

添 加anchor控件到页面上的方法和添加popup控件到页面上非常相似。当你添加了一个anchor控件到页面上之后,你可以选择任何已经存在于服务端 的控件ID,或选择一个你想处理的客户端事件。如果你只是想重新打开popup控件,你只需要保证popup窗口控件会被传到客户端,并且是可见的就行。 如果你不希望popup窗口在页面一载入的时候就显示,可以设置AutoShow属性为false。
你还可以选择使用PopupWinAnchor来改变popup窗口中的文字。设置anchor控件的ChangeTexts属性为True,然后anchor控件会通过NewTitle,NewMessage和NewText设置新的popup窗口文字。

image

代码
下面的例子描述了如何使用PopupWinAnchor控件重新打开刚被关闭的popup窗口。

 

<!-- Anchor.aspx -->
<%@ Register TagPrefix="cc1" Namespace="EeekSoft.Web"
  Assembly
="EeekSoft.Web.PopupWin" %>
 

<cc1:popupwin id="popupWin" runat="server" visible="False"
colorstyle
="Blue" width="230px" height="100px" dockmode="BottomLeft"
windowscroll
="False" windowsize="300, 200"></cc1:popupwin>
<cc1:popupwinanchor id="popupAnchor" runat="server"
changetexts
="False"></cc1:popupwinanchor>
<span id="spanReopen"> Click here to reopen popup ! </span>
 

// Anchor.aspx.cs
// 处理鼠标单击事件
popupAnchor.HandledEvent="onclick";
// .. of spanReopen 元素
popupAnchor.LinkedControl="spanReopen";
// 当事件存在时,显示popup窗口
popupAnchor.PopupToShow="popupWin";
// Popup win is visible ..
popupWin.Visible=true;
// .. and will be displayed when page is loaded
popupWin.AutoShow=true;



在执行时动态加载控件

以前在动态加载控件是有问题的,不过已经被修改了;) 这里是一个动态创建popup窗口的例子。 该例子将会演示当用户单击spanReopen 元素时,动态创建popup窗口。(假设,你的页面上有一个叫spanReopen 的元素)

 

 

// Create popup window and popup win anchor control (in Page_Load)
PopupWin popupWin=new PopupWin();
PopupWinAnchor popupAnchor
=new PopupWinAnchor();
// 添加控件到页面
placeHolder.Controls.Add(popupAnchor);
placeHolder.Controls.Add(popupWin);
// Set anchor properties
popupAnchor.PopupToShow=popupWin.ClientID;
popupAnchor.LinkedControl
="spanReopen";
popupAnchor.HandledEvent
="onclick";
// Set popup win properties
popupWin.ActionType=EeekSoft.Web.PopupAction.MessageWindow;
popupWin.Title
="This is popup";
popupWin.Message
="Message displayed in popup";
// Show popup
popupWin.Visible=true;
popupWin.AutoShow
=false;



用途

该 控件能够很好地用于提示用户重要信息。例如,在web邮件客户端,你可能想提示用户有新消息;在用户可以相互通信的系统中,你可以使用它警告用户有一些人 想和它对话。该控件的优点是,它不需要在页面上占有任何固定的位置,而且很醒目。另外一个可以使用的地方是:用于广告显示,这样就没必要做一个flash 了。

Anchor控件可以使popup控件更快,并且减少页面的重新加载。比如,你可以使用popup控件为一些页面控件显示快速帮助。快速帮助在文本框被聚焦的时候显示,或在文本框后面加一个按钮,当按钮执行时显示。

  • Download demo project (C# and VB.NET) - 38.2 KB
  • Download control with source - 37.7 KB
  • Download control documentation - 71.1 Kb
  • posted @ 2007-11-02 14:11 jueban's space 阅读(888) 评论(1) 编辑

    ASP.NET 2.0 下的验证码控件

    posted @ 2007-11-02 14:01 jueban's space 阅读(894) 评论(1) 编辑

    2007年你必须学习的10项.NET技术

    当然对于这个问题,每个人都有自己的想法。以下只是作为我个人认为比较重要的10项需要学习的技术:
      1、WCF (Windows Communication Foundation):虽然WCF显然没有WPF或SilverLight那么吸引人,但是它却是在.NET框架下解决业务问题的基础。所以你今年至少要学习一门.NET的新技术,那你就选择WCF吧。
      2、ADO.NET (and LINQ):这是让你与数据层打交道的技术。并且LINQ提供了将各种数据组合起来的方法。如果以上两个技术你都不熟悉的话,那就等着被人来抢你饭碗吧。
      3、WPF (Windows Presentation Foundation):学习WPF的重要性简直不言而喻。你在程序中所需要的窗体、交互界面、页面都是架构在WPF上的。并且在Vista中已经集成了WPF。
      4、SQL Server 2005:我明白这其实并不是.NET的内容,但它又确实是.NET的内容。SQL Server 2005为开发者提供了一种在其他平台无法得到的强大力量。你得仔细挖掘这个版本所带来的创新技术,这将帮助你成为一个更好的开发者和问题解决者。
      5、ASP.NET 2.0:即使是非在线程序开发者也应该了解一下这个技术。这代表着最新的概念——动态语言。LINQ,AJAX等崭新的技术都集成在其中(当然,最吸引人的当然是SilverLight!)。
      6、安全:关于这点,我只提一句话:安全顾问专家的薪资已经提高到每小时300美元了。
      7、TDD (Test Driven Development):为了检验你的程序是否正确,你总得测试一下。而如何测试则是一门学问。好好学习测试的学问吧。
      8、Networking:网络部分的基础知识当然都得复习一下,TCP,UDP,HTTP,FTP,等等协议。学习这些将能让你更容易的将各个程序与数据结合起来。并且让你的程序效率更高。
      9、Threading:对于线程的理解将直接决定你的.NET开发水平。你得多学习一下线程相关知识,知道他们是干什么用、并且怎么用在你的程序里的。
      10、Learning:对,我将学习定义为一项技术。人们得学会如何学习,并且选择学习什么。这样你才能前进得更快。

    posted @ 2007-11-02 13:55 jueban's space 阅读(66) 评论(0) 编辑

    创建一个简单的Linq数据库应用程序

    简介
    Linq是一个新的数据库访问技术,然我们对数据库的操作变得如此简单,不过究竟性能、安全等因素是否达到我们需求?本文,带你入门的同时,分析它的这些本质的东西。

    数据库
    在这个简单的应用程序中,我使用了SQL Server 2005作为其数据源,当然你也可以使用XML文件。

    让我们从创建AddressBook数据库开始吧


    我在这个数据库里创建了一个叫Addresses的数据表。


    这张表是非常常用的,唯一特殊的是你必须把id字段设为自动增长型的主键,否则它就会是只读的了。

    应用程序

    创建Linq类
    首先,我们简单地使用VS2008创建一个简单的"LINQ to SQL Class",我把它命名为_AddressBook.dbml

    当设计界面出来后,把Addresses表拖到设计面板中,然后把它重新命名为Addresses(点击顶部重命名).


    到属性框,编辑_AddressBookDataContext的属性,此前,确定已经设定了正确的命名空间和web.config中定义的数据库连接字符串。


    下一步编辑Address数据类,默认的属性也是可以的


    封装类
    创建一个叫AddressBook的类,它事实上是一个_AddressBook的封装类。这个类非常的简单,所有做的事情就是初始化对象,提供一个简单的接口。唯一确保的事情:与_AddressBook相关的命名控件,和配置文件中的数据库连接字符串。

     

    using System.Configuration;
    ///
    /// Summary description for AddressBook
    ///
    namespace Clarity.Database
    {
    public class AddressBook
    {
    private _AddressBookDataContext _AddressBook;
    public AddressBook()
    {
    string conn = ConfigurationManager.ConnectionStrings[
    "AddressBookConnectionString"].ToString();
    _AddressBook 
    = new _AddressBookDataContext(conn);
    }
    public System.Data.Linq.Table Addresses
    {
    get { return _AddressBook.Addresses; }
    }
    }
    }
    应用程序

    这里,我不打算谈如何编译这个应用程序,它不是我要在这篇文章中所说的。下面,我会介绍烦琐的初始化和访问数据库的步骤。

    private AddressBook thisAddressBook = new AddressBook();

     

    你会通过thisAddressBook对象完全控制你的数据库。通过这个对象,你可以查询、插入、更新和删除数据库中的记录。

    加载数据到表格中

    private void LoadGrid()
    {
    GridView1.DataSource 
    = thisAddressBook.Addresses.OrderBy(c => c.LastName);
    GridView1.DataBind();
    }

     

    输出的数据会通过LastName排序。后面的表达式(c => c.LastName),c代表你的对象,就是可以简单地这样使用你的obj(obj => obj.LastName)

    过滤表格中的数据

     

    private void LoadGrid(string filter)
    {
    GridView1.DataSource 
    = thisAddressBook.Addresses.Where(
    => c.LastName.StartsWith(filter)).OrderBy(c => c.LastName);
    GridView1.DataBind();
    }

     

      注意,过滤是必须附带filter变量。

    删除一个记录

    protected void GridView1_RowDeleting(object sender,
    System.Web.UI.WebControls.GridViewDeleteEventArgs e)
    {
    int id = Convert.ToInt32(GridView1.DataKeys[e.RowIndex].Value);
    Addresses thisAddress 
    = thisAddressBook.Addresses.First(x => x.id == id);
    thisAddressBook.Addresses.Remove(thisAddress);
    thisAddressBook.Addresses.Context.SubmitChanges();
    LoadGrid();
    }


    插入和删除一个记录

    protected void AddressUpdated(object sender, UserData.UpdateEvent e)
    {
    Addresses thisAddress;
    int id = e.Address.id;
    // If this value is 0 then add a record
            if (id != 0)
    thisAddress 
    = thisAddressBook.Addresses.First(x => x.id == id);
    else
    thisAddress 
    = new Addresses();
    thisAddress.FirstName 
    = e.Address.FirstName;
    thisAddress.LastName 
    = e.Address.LastName;
    thisAddress.Address1 
    = e.Address.Address1;
    thisAddress.City 
    = e.Address.City;
    thisAddress.State 
    = e.Address.State;
    thisAddress.Zip 
    = e.Address.Zip;
    thisAddress.Email 
    = e.Address.Email;
    // If this value is 0 then add a record
            if (id == 0)
    thisAddressBook.Addresses.Add(thisAddress);
    thisAddressBook.Addresses.Context.SubmitChanges();
    LoadGrid();
    }

    SQL查询
    在做的过程中,我非常关心其实际在数据库中查询的语句。它究竟会不会把所有的数据都载入,然后再过滤?等等……
    不过,我对它的结果是非常满意的。

    LOAD语句的结果

    SELECT [t0].[id][t0].[FirstName],
    [t0].[LastName][t0].[Address1][t0].[City][t0].[State][t0].[Zip],
    [t0].[Email] FROM [dbo].[Addresses] AS [t0] ORDER BY [t0].[LastName]

    不错,和原始的没什么出入。

    过滤语句

    exec sp_executesql N'SELECT
    [t0].[id], [t0].[FirstName], [t0].[LastName], [t0].[Address1], [t0].[City],
    [t0].[State], [t0].[Zip], [t0].[Email] FROM [dbo].[Addresses] AS [t0] WHERE
    [t0].[LastName] LIKE @p0 ORDER BY [t0].[LastName]
    ',N'@p0 nvarchar(2)',@p0=N'H%'


    居然,使用了一个存储过程来防止SQL注入,还挺周到:)

    删除语句

    exec sp_executesql N'DELETE FROM
    [dbo].[Addresses] WHERE ([id] = @p0) AND ([FirstName] = @p1) AND ([LastName] =
    @p2) AND ([Address1] = @p3) AND  ([City] = @p4) AND ([State] = @p5) AND ([Zip]
    = @p6) AND ([Email] = @p7)
    ',N'@p0 int,@p1 nvarchar(5),@p2 nvarchar(5),@p3
    nvarchar(15),@p4  nvarchar(10),@p5 nvarchar(2),@p6 nvarchar(5),
    @p7 nvarchar(15)
    ',@p0=4,@p1=N'Kelly',@p2=N'Smith',@p3=N'123
    Fake  Street
    ',@p4=N'Manchester',@p5=N'NH',@p6=N'03102',@p7=N'kelly@gmail.com'


    和上面的一样

    插入语句

    exec sp_executesql N'INSERT INTO
    [dbo].[Addresses]([FirstName], [LastName], [Address1], [City], [State], [Zip],
    [Email]) VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6)
    SELECT [t0].[id] FROM
    [dbo].[Addresses] AS [t0] WHERE [t0].[id] = (SCOPE_IDENTITY()) 
    ',N'@p0
    varchar(7),@p1 varchar(6),@p2 varchar(15),@p3 varchar(9),@p4 varchar(2),@p5
    varchar(5),@p6  varchar(18)
    ',@p0='John',@p1='Smith',@p2='123 Fake
    Street
    ',@p3='Somewhere',@p4='CT',@p5='03102',@p6='nobody@nowhere.com'

    插入后,得到了最新插入的key值。

    posted @ 2007-11-02 13:52 jueban's space 阅读(163) 评论(0) 编辑

    Visual Studio 2008 In Action 之 Linq,一些操作

    在“SQL时代”我们随机读取一条记录的方法是

     

    SELECT TOP 1 * FROM TABLE1 ORDER BY NEWID()


    当时在LINQ中怎么做?我曾经想当然的用下面的语句,期待他能返回正确的结果

     

    var customer = (from c in ctx.Customers orderby Guid.NewGuid()).First();


    但实际上,LINQ无情地把我那句orderby给过滤掉了,怎么办?难道又要写SQL语句来实现?
    假如ORDERBY只是查询条件中的一小部分呢?所有的东西都写成SQL语句?不用!这里有一个小技巧:

     

    //在自动生成的mapping code中添加
    [Function(Name = "NEWID", IsComposable = true)]
    public Guid NEWID()
    {
        
    return ((Guid)(this.ExecuteMethodCall(this, ((MethodInfo)(MethodInfo.GetCurrentMethod()))).ReturnValue));
    }
    //在使用中
    var customer = (from c in ctx.Customers orderby ctx.NEWID()).First();


    如何执行IN操作
    在BETA2中,Linq加入了对IN操作的支持,使用起来很简单,把Contains反过来用就可以了

     

     string[] tags = new string[] { "aaa""bbb" };
     var result 
    = from p in ctx.Posts
                  join t 
    in ctx.Tags on p.PostId equals t.PostId
                  where tags.Contains(t.Text)
                  select p;


    LINQ会自动帮你生成类似下面的语句

     

    Text IN ('aaa''bbb')


    如何执行LIKE操作
    LIKE也是用Contains来实现,只不过需我们手动用循环组合一下,并且……

     

    string[] keyWords = new string[] { "aaa""bbb" };
    var result 
    = from p in ctx.Posts
                  select p;
      
    foreach(string keyWord in keyWords)
    {
        result 
    = result.Where(p => p.Text.Contains(keyWord));
    }


    LINQ会自动帮你生成类似下面的语句

     

    Text LIKE @p0 AND Text LIKE @p1, @p0=N'%bbb%', @p1=N'%bbb%'


    等一下?为什么两个都是bbb?aaa哪儿去了?这是个BUG么?不是!
    这是LINQ的运行机制造成的,由于LINQ在最终使用数据之前并不生成SQL语句,只是进行查询条件的组合。由于keyWords以Enumerate的方式Pop出来,LINQ拿到的keyWord只是最后的值。
    那我们该怎么办?很简单,一行代码搞定。

      foreach(string keyWord in keyWords)
    {
        
    string key = keyWord;
        result 
    = result.Where(p => p.Text.Contains(key));
    }


    看起来很奇怪是吧?但恰恰就是这么一行看似多余的,一个思维正常的程序员平常绝对不会写的代码,起了重大作用。

    如何返回业务实体到上层逻辑
    几乎所有的Linq教程都是查询然后foreach,甚至可以select匿名类,这在演示中确实是很方便,很酷。但实际应用中,在多层结构流行的今天,谁又会真的这么用呢?我们需要把Linq产生的数据返回给上层,匿名类在这个地方(其他地方,比如逻辑层用来解决一些事情还是比较方便的)除了看起来比较酷以外还有什么其他意义?
    LINQ会为我们的数据表、视图生成Table<T>,但实际应用中,我们会把在UI层引用LINQ所在的工程,然后直接使用这个Table<T>么?至少我不会
    我们需要把Table转换成我们自己定义的实体(Entity/Model)
    select new Entity { ... } 不就完了?没错,但是如果我有类似
    GetUserById(Guid UserId)
    GetAllUsers()
    GetAllActiveUsers()
    是不是要在所有方法中,把这个select写一遍?可不可以把这个select独立成一个方法?
    像之前所说的,LINQ在最终使用数据之前并不生成SQL语句,也就是说在ToList(), Any(), foreach等等之前,你可以任意的组合,反复地查询,这就给我们独立select方法提供了可能。

     private IQueryable<Entities.Tag> TranslateToEntity(IQueryable<Tag> tags)
     {
        
    return from t in tags
                select 
    new Entities.Tag
               {
                   TagId 
    = t.TagId,
                  Text 
    = t.Text,
                   CreateTime 
    = t.CreateTime
               };
    }
    List
    <Entity.Tag> GetAllUsers()
    {
       
    //var users = 
        return TranslateToEntity(users).ToList();
    }


    同样的方法适用于分页等一些会在多出使用的操作。

    posted @ 2007-11-02 12:56 jueban's space 阅读(121) 评论(0) 编辑

    问题描述:制作上传头像缩略图,希望图片能够等比例剪切,类似豆瓣的头像上传功能

    搜索答案:本来以为这样的问题应该很好搜答案,baidu google搜了一遍发现都是直接制作缩略的,没有剪切的功能。因为一直做web,很少用到gdi+的类库,只是了解点而已,按照制作缩略图的方法简单改一下就解决了。

    解决代码:

     

    System.Drawing.Image newImage=System.Drawing.Image.FromFile(Server.MapPath(”upimages/1.gif”));
       Bitmap b
    =new Bitmap(50,50);
       Graphics g
    =Graphics.FromImage(b);
       
    int photoWidth=newImage.Width;
       
    int photoHeight=newImage.Height;
       
    int x=50,y=50;
       
    int x1=50;
       
    if ((photoWidth-photoHeight)>0)
       {
        y
    =0;
        x
    =(photoWidth-photoHeight)/2;

        x1
    =photoHeight;
       }
       
    else
       {
        x
    =0;
        y
    =(photoHeight-photoWidth)/2;
        x1
    =photoWidth;
       }
       GraphicsUnit units 
    = GraphicsUnit.Pixel;
       g.InterpolationMode 
    = System.Drawing.Drawing2D.InterpolationMode.HighQualityBilinear;
       g.DrawImage(newImage, 
    new Rectangle(00, b.Width, b.Height),x, y, x1,x1, units);
       b.Save(Server.MapPath(”
    11.jpg”));

     

     代码很简单 就不用解释了。

    备注: 为什么要把这么简单的方法写个blog呢,还是由于豆瓣的缘故,在豆瓣出现之前做头像的很少象这样直接把客户上传的图片切割的,可能是为了用户图片的完整性吧,但是豆瓣大胆的用这种简单的方法,达到了更好的效果,图片更容易被人看清楚,而且也增加了用户头像的个性。

    有时候技术其实不是最主要的,一个很好的思路就能带动网站的发展。

    下篇研究mop的头像上传功能,也是一个很简单的功能,但是达到了比豆瓣更加直观的效果。敬请期待

    posted @ 2007-11-02 09:33 jueban's space 阅读(378) 评论(0) 编辑

    >做个纪录,转贴一篇怎么备份sql数据库

    using SQLDMO;
    //SQLDMO.DLL 在C:\Program Files\Microsoft SQL Server\80\Tools\Binn

    private void DataBase()
    {
     SQLServer2Class oSqlServer 
    = new SQLServer2Class();
     oSqlServer.LoginSecure 
    = true;
     oSqlServer.Connect(”
    192.168.1.14″,”sa”,”sa”); //数据库的名称、登录名、密码

     Backup2Class oBack 
    = new Backup2Class();
     oBack.Database 
    = “ewremon”;   //要备份的数据库
     oBack.Files = “F:\\ewremon”;   //目标文件
     oBack.Action = SQLDMO_BACKUP_TYPE.SQLDMOBackup_Database;
     
    try
     {
      oBack.SQLBackup(oSqlServer);
     }
     
    catch(Exception ex)
     {
      Response.Write(ex.Message.ToString());
     }
     
    finally
     {
      oBack 
    = null;
     }
    }
     

    posted @ 2007-11-02 09:31 jueban's space 阅读(32) 评论(0) 编辑