一切福田,不離方寸,從心而覓,感無不通。

Category Archives: Programming Language

Asp.net控件开发学习笔记-控件开发基础(一)

  服务器控件开发基础 当开发一个服务器控件时,首先要明白其内部的工作机理。其实在页面内部每一点由asp.net返回的HTML代码无论是简单的<span>标签,或者是button按钮,或者是复杂的gridview控件,都是由继承自System.Web.UI.Control的对象生成的。   控件的属性 控制控件的方法大多是通过控件的属性来操作的,通过控制服务器控件的属性,就可以相应的改变服务器生成的html. 下面是一个服务器控件的属性:    在Visual Studio里,当通过属性窗口来改变控件的属性时,VS会自动将属性添加到对应的aspx的HTML里,而在html内添加属性时,在属性窗口里也会对应显示更改过的属性视图比如: <asp:ButtonID="Button1"runat="server"Text="Button"CommandName="cName"/> 在属性窗口里会对应显示,如下图:        当然某些控件的属性会略有不同,比如常用的Label控件: <asp:LabelID="Label1"runat="server">这里是Text属性</asp:Label> 在开始符号和结束符号之间的内容会被设置成Text属性.   当然,最实用也是我们最常用的是通过C#以编程的方式动态的修改控件的属性.这就不说了.   控件的方法 控件通过方法来操作更加复杂的控件操作,通常在控件的方法内部会有很复杂的过程,一般包括几个内部函数和属性的组合.比如: privatevoid LoadDropDownList() { ArrayList list = new ArrayList(); list.Add("Hello"); list.Add("Goodbye"); GridView1.DataSource = list; GridView1.Databind(); } 这样,通过调用Databind()方法,就可以讲gridview和数据源进行绑定. 控件的事件 控件通过事件来通知其它类或者客户端其内部的某个状态被改变。事件是一种灵活的机制,当控件与客户端进行交互的时候,事件会通过Http Post方法和服务器进行交互,通过自动回传机制,WEB开发中的事件表现起来就会像开发Windows FORM程序一样(当然,速度是无法和Form相比的) 在Visual Studio中,可以在属性窗口中通过黄色的闪电图标来显示和控制控件的事件,如下:   当双击相应的事件后,会在后台产生默认的处理方法,命名规则为”控件名_事件名”           WEB Page本质是一个控件树   在aspx页面的头部将Trace="true"设置到Page后,页面会显示相应的追踪信息,在Control Tree那一节,你会发现整个页面其实就是一个控件树,如图:          根控件? OK,既然asp.net页面的本质是一个控件树,按照C#是完全面向对象的语言惯例(所有的一切都是继承于System.Object),那么所有控件共同的父类是什么? 在asp.net中,所有的控件被分布在3个主要命名空间中,分别为:    System.Web.UI    System.Web.UI.WebControls    System.Web.UI.HtmlControls 它们之间的关系如下图所示     System.Web.UI命名空间 由上图可知,System.Web.UI处于继承树顶端的,而System.Web.UI.Control是所有控件的基础,所有的控件必须强制直接或者间接的继承Control类,而直接继承Control类的是Page类,以及UserControl类。   System.Web.UI.HtmlControls命名空间 在System.Web.UI.HtmlControls命名空间中的对象,通过在html标签中加入runat=”server”属性,能够将HTML中的标签转化为服务器控件。Asp.net的引擎会将的页面中的HTML标签和System.Web.UI.HtmlControls内的对象进行匹配。System.Web.UI.HtmlControls命名空间如图:       未完待续……… http://www.cnblogs.com/CareySon/archive/2009/09/30/1576984.html

龙生   08 Apr 2013
View Details

ASP.NET服务器控件开发(5)--添加客户端功能

  随着Ajax等技术的发展,客户端功能也逐渐变得越来越重要。如果在服务器控件中添加客户端功能,将会创作出功能更强大,界面更丰富的服务器控件。 客户端功能: 在Web编程中,客户端功能传统上是由Web页开发人员负责,并且不被封装在服务器组件中。ASP.NET脱离了这一范畴并使服务器控件能够发出客户端脚本,从而使服务器控件能够将客户端处理与服务器端处理结合起来。例如按钮控件的OnClientClick属性,就可以在其中声明一段脚本在客户端执行。 OnClientClick—>return confirm('Hello Word'),单击按钮时就会在客户端弹出一个提示框。 实现客户端功能的技术主要是客户端脚本(JavaScript、VBScript等)和DHTML。这个想必大家都知道。 ASP.NET服务器控件中客户端功能的实现: 下面我们进入正题,来看看ASP.NET服务器控件中是如何实现客户端功能的:代码如下: namespace ServerClientControl{    [DefaultProperty("Text")]    [ToolboxData("<{0}:SimpleButton runat=server></{0}:SimpleButton>")]publicclass SimpleButton :Button{protectedoverridevoid RenderContents(HtmlTextWriter output){        }protectedoverridevoid AddAttributesToRender(HtmlTextWriter writer){base.AddAttributesToRender(writer);            writer.AddAttribute("onclick", "window.confirm('Hello World! ');");        }    }} 我们创建一个继承自Button的类,通过AddAttributesToRender()方法添加一个onclick客户端事件。这样就简单的实现了向服务器控件添加客户端事件的功能。 ClientScriptManager 类 当然,这只是简单的方式。在 .NET Framework 2.0 版中为我们新增了ClientScriptManager 类。通过在网页的 HTML 标记中包含脚本,可以声明方式向网页添加客户端脚本。然而,有些情况下需要动态添加客户端脚本。 实现复杂客户端功能有关的几个常用方法:RegisterClientScriptBlock():向页的顶部添加一个脚本块。以字符串形式创建脚本,然后将其传递给方法,方法再将脚本添加到页中。可以使用此方法将任何脚本插入到页中。请注意,脚本可能在所有元素完成之前呈现到页中;因此,您可能无法从脚本中引用页上的所有元素。RegisterClientScriptInclude():与 RegisterClientScriptBlock 方法类似,但此方法将添加引用外部 .js 文件的脚本块。包含文件在任何其他动态添加的脚本之前添加;因此,您可能无法引用页上的某些元素。RegisterStartupScript():向页中添加一个脚本块,该脚本块在页完成加载后引发页的 onload 事件之前执行。该脚本通常不创建为事件处理程序或函数;它通常只包含要执行一次的语句。RegisterOnSubmitStatement():添加响应页的 onsubmit 事件而执行的脚本。该脚本在提交页之前执行,允许您取消提交。IsStartupScriptRegistered():确定Page对象是否注册了启动脚本。  IsClientScriptBlockRegistered():确定Page对象是否注册了客户端脚本。 更详细的说明讲解大家可以参看MSDN。 这里还要提下OnPreRender 方法。这个方法触发PreRender 事件。PreRender 事件在加载 Control 对象之后、呈现之前发生。可以理解为准备呈现的意思。在该事件的生存期内可以保存服务器控件视图状态的任何更改。不保存呈现阶段内所做的同样更改。开发人员可以再这个事件中添加脚本处理。 string JsPath ="js/";//重写OnPreRender方法protectedoverridevoid OnPreRender(EventArgs e){            Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "Ajax", "<script language='javascript' src='"+ JsPath +"Ajax.js"+"'></script>");//注册客户端脚本            Page.ClientScript.RegisterStartupScript(this.GetType(),"jQuery", "<script language='javascript' src='"+ JsPath +"jQuery.js"+"'></script>");//注册启动脚本base.OnPreRender(e);        } 这里简单的举个例子,Ajax.js中声明了要调用函数的名称,jQuery中对函数具体的实现。具体功能的代码就根据自己的需求实现啦!本人的js一般,这里就不做例子了。 IScriptControl 接口 IScriptControl接口:定义 ASP.NET 服务器控件为在启用 AJAX 的应用程序中定义JavaScript资源而必须实现的方法。创建将 ASP.NET 的 AJAX 功能用于浏览器中的扩展功能的自定义 Web 服务器控件。 当由类实现时,IScriptControl 接口的方法提供对脚本库的引用,这些脚本库定义客户端组件和表示客户端类型实例的脚本说明符。在将包含脚本控件功能的自定义服务器控件中实现此接口。这样,通过IScriptControl接口也能够实现ASP.NET服务器空间中添加客户端功能。 MSDN上有个通过IScriptControl向Web 服务器控件添加客户端功能的很好的例子。讲解的很详细。感兴趣的朋友可以参看: http://msdn.microsoft.com/zh-cn/asp.net/bb386450.aspx#Mtps_DropDownFilterText 小结:感冒了,就先写到这吧。通过向服务器控件中添加客户端功能,可以很好的增强控件的价值,提高用户客户端的体验。从中我们也不难看出,要想开发出一个好的服务器控件也是满不容易的,不但要对控件的生命周期,.NET提供的类库,接口有所了解,还要对js也要比较熟悉。所以从自定义服务器控件的开发过程中学习到很多知识。 转自:http://www.cnblogs.com/gaoweipeng/archive/2009/06/27/1512248.html

龙生   08 Apr 2013
View Details

ASP.NET服务器控件开发(4)--复合控件

  复合控件 概念:     所谓复合控件:简单的理解就是将多个基本的控件组合成一个控件,从而实现自己想要的效果。微软为ASP.NET2.0中推出的登录控件等就是一个复合控件。从功能的实现上,复合式控件有点像用户控件,只是一个是.ascx文件,一个是.dll文件。 呈现简单的复合控件: 要想呈现一个复合控件,需要了解以下几个方面: -->实现INamingContainer接口。 任何实现该接口的控件都创建一个新的命名空间,在这个新的命名空间中,所有子控件 ID 属性在整个应用程序内保证是唯一的。 -->Control.CreateChildControls 方法。 由 ASP.NET 页面框架调用,以通知使用基于合成的实现的服务器控件创建它们包含的任何子控件,以便为回发或呈现做准备。 当开发复合服务器控件或模板服务器控件时,必须重写此方法。重写 CreateChildControls 方法的控件应实现 INamingContainer 接口以避免命名冲突。    -->Control.ChildControlsCreated 属性。 获取一个值,该值指示是否已创建服务器控件的子控件。    -->Control.EnsureChildControls 方法。 确定服务器控件是否包含子控件。如果不包含,则创建子控件。    下面就通过实例来呈现个简单的复合登陆控件:创建ASP.NET服务器控件工程。complexControl。 先来看代码: namespace complexControl{    [DefaultProperty("Text")]    [ToolboxData("<{0}:LoginControl runat=server ButtonText='登录' NameLabel='用户名:' PasswordLabel='用户密码:'></{0}:LoginControl>")]publicclass LoginControl : WebControl, INamingContainer, IPostBackEventHandler{private Button _button;private TextBox _nameTextBox;private Label _nameLabel;private TextBox _passwordTextBox;private Label _passwordLabel;private RequiredFieldValidator _nameValidator;private RequiredFieldValidator _passwordValidator;        [Bindable(true),Category("Appearance"),DefaultValue(""),Description("按钮文本")]publicstring ButtonText{get{                EnsureChildControls();//确定服务器控件是否包含子控件return _button.Text;            }set{                EnsureChildControls();                _button.Text = value;            }        }        [Bindable(true),Category("Default"),DefaultValue(""),Description("姓名")]publicstring Name{get{                EnsureChildControls();return _nameTextBox.Text;            }set{                EnsureChildControls();                _nameTextBox.Text = value;            }        }        [Bindable(true),Category("Appearance"),DefaultValue(""),Description("必须输入姓名")]publicstring NameErrorMessage{get{                EnsureChildControls();return _nameValidator.ErrorMessage;            }set{                EnsureChildControls();                _nameValidator.ErrorMessage = value;                _nameValidator.ToolTip = value;            }        }        [Bindable(true),Category("Apperance"),DefaultValue(""),Description("姓名标签")]publicstring NameLabel{get{                EnsureChildControls();return _nameLabel.Text;            }set{                EnsureChildControls();                _nameLabel.Text = value;            }        }        [Browsable(false),DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]publicstring Password{get{                EnsureChildControls();return _passwordTextBox.Text;            }        }        [Bindable(true),Category("Appearance"),DefaultValue(""),Description("必须输入密码")]publicstring PasswordErrorMessage{get{                EnsureChildControls();return _passwordValidator.ErrorMessage;            }set{                EnsureChildControls();                _passwordValidator.ErrorMessage = value;                _passwordValidator.ToolTip = value;            }        }        [Bindable(true),Category("Appearance"),DefaultValue(""),Description("密码标签")]publicstring PasswordLabel{get{                EnsureChildControls();return _passwordLabel.Text;            }set{                EnsureChildControls();                _passwordLabel.Text = value;            }        }protectedoverridevoid CreateChildControls(){            Controls.Clear();            _nameLabel =new Label();            _nameTextBox =new TextBox();            _nameTextBox.ID ="nameTextBox";            _nameValidator =new RequiredFieldValidator();            _nameValidator.ID ="validator1";            _nameValidator.ControlToValidate = _nameTextBox.ID;            _nameValidator.Text ="*";            _nameValidator.Display = ValidatorDisplay.Static;            _passwordLabel =new Label();            _passwordTextBox =new TextBox();            _passwordTextBox.TextMode = TextBoxMode.Password;            _passwordTextBox.ID ="passwordTextBox";            _passwordValidator =new RequiredFieldValidator();            _passwordValidator.ID ="validator2";            _passwordValidator.ControlToValidate = _passwordTextBox.ID;            _passwordValidator.Text ="*";            _passwordValidator.Display = ValidatorDisplay.Static;            _button =new Button();            _button.ID ="button1";//_button.Click += new EventHandler(_button_Click);            _button.CommandName ="ClickLogin";this.Controls.Add(_nameLabel);this.Controls.Add(_nameTextBox);this.Controls.Add(_nameValidator);this.Controls.Add(_passwordLabel);this.Controls.Add(_passwordTextBox);this.Controls.Add(_passwordValidator);this.Controls.Add(_button);        }protectedoverridevoid Render(HtmlTextWriter writer){            AddAttributesToRender(writer);            writer.AddAttribute(HtmlTextWriterAttribute.Cellpadding,"1", false);            writer.RenderBeginTag(HtmlTextWriterTag.Table);            writer.RenderBeginTag(HtmlTextWriterTag.Tr);            writer.RenderBeginTag(HtmlTextWriterTag.Td);            _nameLabel.RenderControl(writer);            writer.RenderEndTag();  // Td            writer.RenderBeginTag(HtmlTextWriterTag.Td);            _nameTextBox.RenderControl(writer);            writer.RenderEndTag();  // Td            writer.RenderBeginTag(HtmlTextWriterTag.Td);            _nameValidator.RenderControl(writer);            writer.RenderEndTag();  // Td            writer.RenderEndTag();  // Tr            writer.RenderBeginTag(HtmlTextWriterTag.Tr);            writer.RenderBeginTag(HtmlTextWriterTag.Td);            _passwordLabel.RenderControl(writer);            writer.RenderEndTag();  // Td            writer.RenderBeginTag(HtmlTextWriterTag.Td);            _passwordTextBox.RenderControl(writer);            writer.RenderEndTag();  // Td            writer.RenderBeginTag(HtmlTextWriterTag.Td);            _passwordValidator.RenderControl(writer);            writer.RenderEndTag();  // Td            writer.RenderEndTag();  // Tr            writer.RenderBeginTag(HtmlTextWriterTag.Tr);            writer.AddAttribute(HtmlTextWriterAttribute.Colspan, "2");            writer.AddAttribute(HtmlTextWriterAttribute.Align, "right");            writer.RenderBeginTag(HtmlTextWriterTag.Td);            _button.RenderControl(writer);//writer.AddAttribute(HtmlTextWriterAttribute, Page.GetPostBackEventReference(_button));            writer.RenderEndTag();  // Td            writer.RenderBeginTag(HtmlTextWriterTag.Td);            writer.Write("&nbsp;");            writer.RenderEndTag();  // Td            writer.RenderEndTag();  // Tr            writer.RenderEndTag();  // Table        }    }} 首先我们实例化了几个现有控件的对象。然后声明了一大堆的属性,要注意的:和平时定义属性不同,我们在每一个属性中都添加了EnsureChildControls ()方法。其他的没有任何变化,和一般的属性声明一样。 接下来我们从写了重要的CreateChildControls()。将前面声明好的实例化控件对象添加到controlcollection中。融合成一个控件。 最后重写控件显示的Render()方法。生成登录窗体的样式。效果如下: 这样,我们基本上就完成了复合控件的基本显示功能。 复合控件的事件处理: 由于复合控件中包含子控件,这就使得复合控件的事件处理变得复杂起来。由于不允许开发人员直接访问子控件,如果子控件的事件不能作为顶级事件引发,那么将无法实现子控件的事件处理。 我们可以以两种形式来完成事件的处理:一是直接将事件封装到控件中,显然灵活性很差。二就是自定义事件,用户来完成事件的代码。 第一种情况比较简单:就是在创建我们得控件时,将要实现的效果直接封装在dll中。这里就不做说明了。 但是往往控件触发时,我们想做自己的事情,这就是第二种情况的事件处理。这就需要把事件交给主控件,由主控件统一暴露事件,这样开发人员在使用控件时仅需要为主控件注册事件即可,剩下的由主控件负责引发子控件的事件或执行子控件的某些功能,这里就涉及主控件与其子控件的事件衔接问题,复合控件的这种事件处理,主要是实现子控件事件上传的过程。一般分为:包含法和冒泡法两种处理方式。 -->包含法: 基本思想是:通过在子控件的事件处理程序中调用复合控件的顶层事件处理程序,以完成子控件的事件上传。 在CreateChildControls方法中,为子控件添加事件处理程序。 接着上面登陆控件的例子,来实现下登录按钮的事件。 首先在CreateChildControls()中,为_button添加单击事件。(其他代码略) _button =new Button();            _button.ID ="button1";             _button.Click +=new EventHandler(_button_Click); 然后创建主控件对外的处理函数: void _button_Click(Object source, EventArgs e){            OnClickLogin(EventArgs.Empty);        }privatestaticreadonlyobject EventClickLogin =newobject();publicevent EventHandler ClickLogin{            add{                Events.AddHandler(EventClickLogin, value);            }            remove{                Events.RemoveHandler(EventClickLogin, value);            }        }protectedvirtualvoid OnClickLogin(EventArgs e){            EventHandler clickLoginHandler = (EventHandler)Events[EventClickLogin];if (clickLoginHandler !=null){                clickLoginHandler(this, e);            }        }publicvoid RaisePostBackEvent(string eventArgument)//处理回发事件{            OnClickLogin(new EventArgs());        } 事件的详细处理请参看上一篇。这里要说明的是:在按钮的单击事件处理函数中,将我们在主控件中声明的事件传入进去: void _button_Click(Object source, EventArgs e){     OnClickLogin(EventArgs.Empty);} 这样,我们就实现了第一种方法。测试一下: protectedvoid LoginControl1_ClickLogin1(object sender, EventArgs e){     Label1.Text ="sssssssssssssssqwwssss";} 单击按钮,将触发上面的事件。 -->冒泡法: 基本思想:使用ASP.NET 2.0框架提供的事件上传机制。这种机制允许子控件将事件沿其包容层次结构向上传播到合适的位置引发,并且允许将事件处理程序附加到原始控件以及公开冒泡的事件的控件上。 冒泡法的实现,使用Control基类中专门用于事件上传的两个方法:OnBubbleEvent和RaiseBubbleEvent。OnBubbleEvent方法用于确定子控件的事件是否沿复合控件层次结构向上传递。在该方法中,参数source表示事件源,参数args表示包含事件数据的EventArgs对象。如果子控件的事件向上传递,则为true;否则为false。默认值为false。RaiseBubbleEvent方法用于将所有事件源及其信息分配给控件的父级,并且不能被重写。尽管无法重写此方法,但创作的控件可以通过重写 OnBubbleEvent 方法处理或引发冒泡事件。 还是通过例子说明一下: 首先在CreateChildControls()中声明commandname属性。 _button.CommandName ="ClickLogin"; 然后定义事件: privatestaticreadonlyobject EventClickLogin =newobject();publicevent EventHandler ClickLogin{            add{                Events.AddHandler(EventClickLogin, value);            }            remove{                Events.RemoveHandler(EventClickLogin, value);            }        }protectedvirtualvoid OnClickLogin(EventArgs e){            EventHandler clickLoginHandler = (EventHandler)Events[EventClickLogin];if (clickLoginHandler !=null){                clickLoginHandler(this, e);            }        }protectedoverridebool OnBubbleEvent(object source, EventArgs e){bool handled =false;if (e is CommandEventArgs){                CommandEventArgs ce = (CommandEventArgs)e;if (ce.CommandName =="ClickLogin"){                    OnClickLogin(EventArgs.Empty);                    handled =true;                }            }return handled;        }publicvoid RaisePostBackEvent(string eventArgument)//处理回发事件{            OnClickLogin(new EventArgs());        } 里主要要注意的是:OnBubbleEvent()的使用。通过CommandName的值,来相应的找到处理事件的控件。 测试一下: protectedvoid LoginControl1_ClickLogin1(object sender, EventArgs e){     Label1.Text ="sssssssssssssssqwwssss";} 单击按钮,将触发上面的事件。 小结:这样,复合控件的基本使用就介绍完了,不是很难。只要记住特定的一些东西,就可以很容易的创造出复合控件。值得大家注意的是复合控件中事件的两种处理方法。希望对新手有帮助。 转自:http://www.cnblogs.com/gaoweipeng/archive/2009/06/23/1507554.html

龙生   08 Apr 2013
View Details

ASP.NET服务器控件开发(3)--事件和回传数据的处理

  前两篇介绍了服务器控件的基本显示,属性的设定,继承Webcontrol开发控件等内容,这篇介绍下定制服务器控件的事件的处理和回传数据的处理。 当ASP.NET页面处理回传到服务器端的表单时,两种信息会传递给页面中的控件: 回传事件,如Button一类控件触发的回传,会引发服务器端事件; 回传数据:是Web表单中包含的数据,该数据是在Web表单提交到服务器端时传递给如TextBox一类的控件。 处理回传数据 PostBack(回传):ASP.NET控件提交表单到服务器端,将信息从浏览器传递到服务器端的过程。 我们可能经常会在Page_Load事件中写这样的代码: protectedvoid Page_Load(object sender, EventArgs e)        {if (!IsPostBack)            {.            }        } 但是初学的时候我们很少回去问,为什么要写这段代码,只知道这么写就是对的。其实这就是数据回传的一个表现,通过该值指示该页是否正为响应客户端回发而加载。 ASP.ENT服务器控件处理回传数据,基本上完成以下两个工作: -->继承并实现IPostBackDataHandler接口的  -->实现RaisePostDataChangedEvent方法,处理回发数据 通过例子说明一下,这里创建一个自己的文本框:创建一个ASP.NET服务器控件项目(MyTextBox) Codenamespace NewTextBox{    [DefaultProperty("Text")]    [ToolboxData("<{0}:NewTextBox runat=server></{0}:NewTextBox>")]publicclass NewTextBox : WebControl, IPostBackDataHandler    {publicevent EventHandler TextChanged; publicstring ViewText//定义显示文字属性        {get            {if (ViewState["Text"].Equals(null))                {return String.Empty;                }else                {return ViewState["Text"].ToString();                }            }set            {                ViewState["Text"] = value;            }        } protectedoverride HtmlTextWriterTag TagKey//向页面中添加文本框        {get            {return HtmlTextWriterTag.Input;            }        } protectedoverridevoid AddAttributesToRender(HtmlTextWriter writer)        {            writer.AddAttribute(HtmlTextWriterAttribute.Type, "text");            writer.AddAttribute(HtmlTextWriterAttribute.Value, ViewText);            writer.AddAttribute(HtmlTextWriterAttribute.Name, this.UniqueID); base.AddAttributesToRender(writer);        } publicbool LoadPostData(string postDataKey, System.Collections.Specialized.NameValueCollection postCollection)//表单域的值和控件的ViewText(此示例中)属性的当前值不匹配,那么将新的值赋给ViewText属性,并且返回True。只有当LoadPostData返回True的时候,才会调用RaisePostDataChangedEvent方法。        {if (postCollection[postDataKey] != ViewText)            {                ViewText = postCollection[postDataKey];returntrue;            }returnfalse;        } publicvoid RaisePostDataChangedEvent()        {if (TextChanged !=null)                TextChanged(this, EventArgs.Empty);        }     }} 测试一下: protectedvoid Button1_Click(object sender, EventArgs e)        {            Label1.Text = NewTextBox1.ViewText;        } 只有当文本框中是文字发生变化是,才会引起数据的回发并从新获得数据。(控件拖到页面时,要给viewText赋值)   处理回发事件 ASP.NET服务器控件处理回发事件,基本上需要完成以下两个工作: -->继承并实现IPostBackEventHandler接口的  -->实现RaisePostBackEvent方法,处理回发事件 Button控件继承IPostBackEventHandler接口(所有的按钮控件,ImageButton,LinkButtton都继承了这个接口)。IPostBackEventHandler接口专门定义了处理回发事件的方法,如果自定义控件需要处理回发事件,你就需要继承IPostBackEventHandler接口。 通过例子说明一下,这里我们定制一个自己的按钮:创建一个ASP.NET服务器控件项目(MyButton) Codenamespace MyButton{    [DefaultProperty("Text")]    [ToolboxData("<{0}:MyButton runat=server></{0}:MyButton>")]publicclass MyButton : WebControl, IPostBackEventHandler    {privatestaticreadonlyobject ClickKey =newobject(); publicevent EventHandler Click //定义事件的委托        {            add            {                Events.AddHandler(ClickKey, value);            }            remove            {                Events.RemoveHandler(ClickKey, value);            }        } protectedvirtualvoid OnClick(EventArgs e)//定义单击事件的处理程序        {            EventHandler clickEventDelegate = (EventHandler)Events[ClickKey]; if (clickEventDelegate !=null)            {                clickEventDelegate(this, e);            }        } publicvoid RaisePostBackEvent(string eventArgument)//处理回发事件        {            OnClick(new EventArgs());        } protectedoverridevoid RenderContents(HtmlTextWriter output)        {            output.Write("<INPUT TYPE=submit name="+this.UniqueID +" Value='这是自己定制的按钮!' />");        }    }} 测试一下: protectedvoid MyButton1_Click(object sender, EventArgs e)        {            Label1.Text ="Hello World!!!!!!!!!";        } 按钮的事件回发处理成功。 客户端回发事件 在asp.net2.0中,Button 控件多了一个UseSubmitBehavior 属性,指示 Button 控件使用客户端浏览器的提交机制(客户端回发)还是 ASP.NET 回发机制,默认采用ASP.NET回发机制,如果设置为false的话,则需要调用GetPostBackEventReference 方法来返回 Button 的客户端回发事件。 当设置UseSubmitBehavior 属性为flase时,运行页面时,则会发现一段自动生成的javascript代码(查看源文件) Code<script type="text/javascript">//<![CDATA[var theForm = document.forms['form1'];if (!theForm) {    theForm = document.form1;}function __doPostBack(eventTarget, eventArgument) {if (!theForm.onsubmit || (theForm.onsubmit() !=false)) {        theForm.__EVENTTARGET.value = eventTarget;        theForm.__EVENTARGUMENT.value = eventArgument;        theForm.submit();    }}//]]></script> 这里我们创建一个按钮,根据属性的设定,更改其事件回发的方式: Codenamespace MyLinkButton{    [DefaultProperty("Text")]    [ToolboxData("<{0}:MyLinkButton runat=server></{0}:MyLinkButton>")]publicclass MyLinkButton : WebControl, IPostBackEventHandler    {publicvirtual ButtonDisplay Display        {get            {object display = ViewState["Display"];if (display ==null)return ButtonDisplay.Button;elsereturn (ButtonDisplay)display;            }set            {                ViewState["Display"] = value;            }        } publicvirtualstring Text        {get            {object text = ViewState["Text"];if (text ==null)returnstring.Empty;elsereturn (string)text;            }set            {                ViewState["Text"] = value;            }        } privatestaticreadonlyobject ClickKey =newobject(); publicevent EventHandler Click//定义委托        {            add            {                Events.AddHandler(ClickKey, value);            }            remove            {                Events.RemoveHandler(ClickKey, value);            }        } protectedvirtualvoid OnClick(EventArgs e)//定义Click事件处理函数        {            EventHandler clickEventDelegate =               (EventHandler)Events[ClickKey];if (clickEventDelegate !=null)            {                clickEventDelegate(this, e);            }        } publicvoid RaisePostBackEvent(string argument)        {             OnClick(EventArgs.Empty);        } overrideprotectedvoid Render(HtmlTextWriter writer)        {base.Render(writer);            Page.VerifyRenderingInServerForm(this); if (Display == ButtonDisplay.Button)            {                writer.Write("<INPUT type=\"submit\"");                writer.Write(" name=\"" + this.UniqueID + "\"");                writer.Write(" id=\"" + this.UniqueID + "\"");                writer.Write(" value=\"" + Text + "\"");                writer.Write(" />");            }elseif (Display == ButtonDisplay.Hyperlink)            {                writer.Write("<A href=\"");                writer.Write(Page.ClientScript.GetPostBackClientHyperlink(this, ""));                writer.Write("\">" + Text + "</A>");            }        } publicenum ButtonDisplay        {            Button =0,            Hyperlink =1        }     } } 根据属性Display的属性的设置,对事件的回发进行控制,如果是Hyperlink则是客户端回发机制。   小结:新手在对事件的回发上可能会迷糊,但是不要紧,慢慢的理解。简单的理解事件的回发就是我们点击一个按钮发生的事件,而这个事件的处理ASP.NET给我们提供了两种方式。更多ASP.NET服务器控件事件可以参考: http://msdn.microsoft.com/zh-cn/library/cc437696(VS.71).aspx http://msdn.microsoft.com/zh-cn/library/xax2hw3x.aspx 写的不好,希望能对新手有帮助。 转自:http://www.cnblogs.com/gaoweipeng/archive/2009/06/19/1506243.html

龙生   08 Apr 2013
View Details

ASP.NET服务器控件开发(2)--继承WebControl类

  前篇文章简单介绍了如何封装Html来创建我们的ASP.NET服务器控件。这篇说说如何继承ASP.NET独有的WebControl类来制作标准服务器控件。 先来介绍下WebControl类 WebControl类: WebControl 类从 Control 派生,用作定义 System.Web.UI.WebControls 命名空间中的所有控件的公共方法、属性和事件的基类。提供所有 Web 服务器控件的公共属性、方法和事件。通过设置在此类中定义的属性,可以控制 Web 服务器控件的外观和行为。主要的属性有:AccessKey、Attributes、 Width、Height等。此外,一个从 WebControl 派生的控件也自行参与到 ASP.NET 的主题功能。WebControl类的属性和方法详细的内容可以参看MSDN。 这里再简单的说下WebControl和HtmlContrlol的区别: Web控件和Html控件虽然好多功能相同并且长得很像,但是它们的内部实现机制是完全不一样的。 Web控件具有回送功能,能够用ViewState维持控件的状态。Html控件则不能,当点击页面的操作,其状态就会丢失。(ViewState后面会有讲解) Html控件与Web控件最大的区别是它们对事件处理的方法不同。对于Html窗体控件,当引发一个事件时,浏览器会处理它。但对于Web控件,事件仅由浏览器生成,但浏览器不会处理它,客户端要给服务器发个信息,告诉服务器处理事件。 不过有些事件,比如:按下键/移动/鼠标等事件,Asp.net中没有这些事件(因为这些事件即时性强,服务器处理得不够及时),这时候Html控件就发挥其作用了,结合Html事件协助完成。 有的资料上说:Web控件要比Html控件执行效率要好。这个没有太好的依据,仅供大家参考,高手也可以谈谈自己的想法。 自己动手: 这里我们不像上篇文章那样,简单的创建一个类库工程,而是直接创建ASP.NET服务器控件项目。 VS2008会自动的为我们生成如下代码: Codenamespace SelfServerControl{    [DefaultProperty("Text")]    [ToolboxData("<{0}:MyControl runat=server></{0}:MyControl>")]publicclass MyControl : WebControl    {        [Bindable(true)]        [Category("Appearance")]        [DefaultValue("")]        [Localizable(true)]publicstring Text        {get            {                String s = (String)ViewState["Text"];return ((s ==null) ?"["+this.ID +"]" : s);            } set            {                ViewState["Text"] = value;            }        } protectedoverridevoid RenderContents(HtmlTextWriter output)        {            output.Write(Text);        }    }}   代码说明: 是不是有点熟悉,很像上节课继承自Control类生成ASP.NET服务器控件的代码。 代码中定义了一个 Text 属性(属性的声明和上篇基本一样),并使用视图状态(ViewState )存储该属性值。使用视图状态保存回发间的 Text 值。每次回发时,将重新创建页并从视图状态还原值。如果 Text 值并未存储在视图状态中,则在每次回发时会将值设置为其默认的 Empty。ViewState 属性继承自 WebControl,是保存数据值的字典。通过使用 String 键,可输入和检索值。代码中将“Text”用作键。字典中的项被类型化为 Object,然后必须将其强制转换为属性类型。 ViewState想必大家都已经很熟悉了,简单的理解:当aspx页面重新加载后,为了避免上一次的存放在变量中的数据丢失,用ViewState来保存。 RenderContents 方法: 通常,在从 WebControl 派生控件并呈现单个元素时,应重写 RenderContents 方法(而不是 Render 方法),以呈现控件标记中的内容。在呈现控件及其样式属性的开始标记之后,WebControl 的 Render 方法将调用 RenderContents。如果重写 Render 方法以写入内容,则控件将丢失生成到 WebControl 的 Render 方法中的样式呈现逻辑。 如果我们将上篇的代码复制到这里,也能得到同样的效果。这里就不做演示了。 WebControl类为开发人员提供了几个特殊的方法,来完成我们对标注服务器控件的开发: AddAttributesToRender(HtmlTextWriter.writer):WebControl的子类应该重写该方法,以便包含用于呈现最外层HTML元素的HTML属性的代码块RenderBeginTag(HtmlTextWriter writer):WebControl的子类应该重写该方法,以便包含用于呈现最外层HTML元素的打开标记的代码块RenderContents(HtmlTextWriter writer): WebControl的子类应该重写该方法,以便包含用于呈现最外层HTML元素的打开和关闭标记之间嵌套的HTML的代码块。RenderEndTag(HtmlTextWriter writer):WebControl的子类应该重写该方法,以便包含用于呈现最外层HTML元素的关闭标记的代码块 实现WebControl类的Render方法: protectedinternaloverridevoid Render(HtmlTextWriter writer) {   RenderBeginTag(writer);   RenderContents(writer);   RenderEndTag(writer); } AddAttributesToRender方法中发生了什么。该方法将在RenderBeginTag方法中被调用。 具体的实例在这里就不做了,给大家一个参看的例子。 简单应用: ASP.NET给我们提供了很多现成的控件,比如Label,button,textbox等等。在平时的开发中,我们完全可以不继承Webcontrol类,直接继承它下面控件的子类,这样更有助于我们项目中的应用和开发。下面说个以前在项目中用到的小实例。 Codenamespace MyTextBox{    [DefaultProperty("Text"), ToolboxData("<{0}:BrianTextBox runat=server></{0}:BrianTextBox>"), Designer("System.Web.UI.Design.WebControls.PreviewControlDesigner, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")]publicclass BrianTextBox : System.Web.UI.WebControls.TextBox    {///<summary>/// 构造函数///</summary>public BrianTextBox()            : base()        {base.Attributes.Add("onfocus", "this.className='"+ onFocus +"';");base.Attributes.Add("onblur", "this.className='"+ onBlurCss +"';");base.CssClass = Class;        } privatestring _onFocusCss ="colorfocus";        [Bindable(true), Category("Appearance"), Description("文本框获取焦点时触发")]///<summary>/// 获取焦点时样式///</summary>publicstring onFocus        {get { return _onFocusCss; }set { _onFocusCss = value; }        } privatestring _onBlurCss ="colorblur";        [Bindable(true), Category("Appearance"), Description("文本框失去焦点时触发")]///<summary>/// 失去焦点时样式///</summary>publicstring onBlurCss        {get { return _onBlurCss; }set { _onBlurCss = value; }        } privatestring _Class ="colorblur";        [Bindable(true), Category("Appearance"), DefaultValue("")]///<summary>/// 样式///</summary>publicstring Class        {get { return _Class; }set { _Class = value; }        } ///<summary>/// 获取焦点的控件ID(如提交按钮等)///</summary>        [Bindable(true), Category("Appearance"), DefaultValue("")]publicstring SetFocusButtonID        {get            {object o = ViewState[this.ClientID +"_SetFocusButtonID"];return (o ==null) ?"" : o.ToString();            }set            {                ViewState[this.ClientID +"_SetFocusButtonID"] = value;if (value !="")                {this.Attributes.Add("onkeydown", "if(event.keyCode==13){document.getElementById('"+ value +"').focus();}");                }            }        }    }} 代码不是很难,简单说下。这里我不是继承自WebControl类,而是继承自它的子类TextBox类,向父类中添加了两个属性,分别代表失去焦点时的样式和获取焦点时的样式。还有一个属性是获取焦点的控件ID。这里默认的设定了css的类名称,所以在使用时,需要创建两个css: Code<style>    .colorblur{        cursor:hand;        background-color:Aquamarine;}         .colorfocus{        cursor:hand;        background-color:Red;}    </style> 不用做其他的任何设置,运行,会看到当我们得Textbox获得焦点的时候背景色红色,失去焦点时,背景是蓝色。,当然,这里只是做个例子,获得和失去焦点的样式大家可以自己去设计。 这只是简单的小应用,给大家提个思路。大家完全可以开动自己创新思维,创造出自己独特的服务器控件。灵活的运用在我们得项目开发中。 转自:http://www.cnblogs.com/gaoweipeng/archive/2009/06/16/1502952.html

龙生   08 Apr 2013
View Details

ASP.NET服务器控件开发(1)--封装html

  在我们的项目开发中,由于ASP.NET的服务器控件功能有限,所以我们经常会自己定义特定的服务器控件,来满足开发中特定的业务要求。可见知道如何开发ASP.NET服务器控件是非常有必要的。 其实简单的实现ASP.NET服务器控件不是很难,以前园子中也有大牛介绍过相应的内容,这里站在巨人的肩膀上也来分享下开发ASP.NET服务器控件的方法和自己的一些体会。写给新手,高手绕过。 学习ASP.NET的服务器控件开发,个人认为最好的方式就是自己去实践,当然理论知识也是很重要的,但是如果我们只是看理论的知识,可能会被里面的一些概念闹糊涂,看着看着就睡着了,如果自己动手创做出一个自己的控件,效果就不一样了。 下面就通过实例创建一个简单的服务器控件: 首先我们创建一个类库工程SelfWebControl。在同一解决方案中我们在创建一个ASP,NET Web应用程序(用来测试我们得控件) namespace SelfWebControl{publicclass ControlA:Control//Control类中定义了所有ASP.NET服务器控件共享的属性和方法    {     }} 我将ControlA类继承Control类,Control类是.NET中所有控件的基类,其中包含了控件共有的属性和方法。 Control类 公共属性: ClientID 获取由 ASP.NET 生成的服务器控件标识符。  Controls 获取 ControlCollection 对象,该对象表示 UI 层次结构中指定服务器控件的子控件。  EnableViewState 获取或设置一个值,该值指示服务器控件是否向发出请求的客户端保持自己的视图状态以及它所包含的任何子控件的视图状态。  ID 获取或设置分配给服务器控件的编程标识符。  NamingContainer 获取对服务器控件的命名容器的引用,此引用创建唯一的命名空间,以区分具有相同 Control.ID 属性值的服务器控件。  Page 获取对包含服务器控件的 Page 实例的引用。  Parent 获取对页 UI 层次结构中服务器控件的父控件的引用。  Site 获取有关服务器控件所属 Web 站点的信息(原文自MSDN,但是我认为不对,应该是指组件的“容器”站点,并非 web site)。  TemplateSourceDirectory 获取包含当前服务器控件的 Page 或 UserControl 的虚拟目录。  UniqueID 获取服务器控件的唯一的、以分层形式限定的标识符。  Visible 获取或设置一个值,该值指示服务器控件是否作为 UI 呈现在页上。 公共方法: DataBind 将数据源绑定到被调用的服务器控件及其所有子控件。  Dispose 使服务器控件得以在从内存中释放之前执行最后的清理操作。  Equals(从 Object 继承) 已重载。确定两个 Object 实例是否相等。  FindControl 已重载。在当前的命名容器中搜索指定的服务器控件。  GetHashCode(从 Object 继承) 用作特定类型的哈希函数,适合在哈希算法和数据结构(如哈希表)中使用。  GetType(从 Object 继承) 获取当前实例的 Type。  HasControls 确定服务器控件是否包含任何子控件。  RenderControl 将服务器控件的内容输出到所提供的 HtmlTextWriter 对象中;如果已启用跟踪功能,则存储有关控件的跟踪信息。  ResolveUrl 根据传递给 TemplateSourceDirectory 属性的值,将相对 URL 解析为绝对 URL。  ToString(从 Object 继承) 返回表示当前 Object 的 String。 公共事件: DataBinding 当服务器控件绑定到数据源时发生。  Disposed 当从内存释放服务器控件时发生,这是请求 ASP.NET 页时服务器控件生存期的最后阶段。  Init 当服务器控件初始化时发生;初始化是控件生存期的第一步。服务器控件应执行任何创建和设置实例所需的初始化步骤。在该事件内无法使用视图状态信息;它尚未填充。在该事件的生存期内不应访问其他服务器控件,不论它是此控件的子级还是父级。不一定会创建其他服务器控件,也不一定能够访问它们。 Load 当服务器控件加载到 Page 对象中时发生。通知服务器控件执行任何设置为在每次页请求时发生的处理步骤。开发者可以访问视图状态信息并利用该事件形成 POST 数据。还可以访问页控件层次结构内的其他服务器控件。 PreRender 当服务器控件将要呈现给其包含的 Page 对象时发生。使用该事件在服务器控件呈现给页的输出之前执行任何更新。在该事件的生存期内可以保存服务器控件视图状态的任何更改。不保存呈现阶段内所做的同样更改。 Unload 当服务器控件从内存中卸载时发生。 保护的属性: ChildControlsCreated 获取一个值,该值指示是否已创建服务器控件的子控件。  Context 为当前 Web 请求获取与服务器控件关联的 HttpContext 对象。  Events 获取控件的事件处理程序委托列表。此属性为只读。  HasChildViewState 获取一个值,该值指示当前服务器控件的子控件是否具有任何已保存的视图状态设置。  IsTrackingViewState 获取一个值,该值指示服务器控件是否将更改保存到其视图状态。  ViewState 获取状态信息的字典,这些信息使您可以在同一页的多个请求间保存和还原服务器控件的视图状态。  ViewStateIgnoresCase 获取一个值,该值指示 StateBag 对象是否不区分大小写。  受保护的方法: AddParsedSubObject 通知服务器控件某个元素(XML 或 HTML)已经过语法分析,并将该元素添加到服务器控件的 ControlCollection 对象。  ClearChildViewState 删除服务器控件的所有子控件的视图状态信息。  CreateChildControls 通知使用基于合成的实现的服务器控件创建它们包含的任何子控件,以便为回发或呈现做准备。  CreateControlCollection 创建一个新的 ControlCollection 对象来保存服务器控件的子控件(包括文本控件和服务器控件)。 EnsureChildControls 确定服务器控件是否包含子控件。如果不包含,则创建子控件。  Finalize(从 Object 继承) 已重写。允许 Object 在“垃圾回收”回收 Object 之前尝试释放资源并执行其他清理操作。  IsLiteralContent 确定服务器控件是否只包含文字内容。Asp.net页面中普通的html标签被asp.net编译为一个 LiteralContent控件(意味着轻型控件)。 LoadViewState 从 SaveViewState 方法保存的上一个页请求还原视图状态信息。  MapPathSecure 如果请求服务器控件有足够的安全权限读取映射结果,检索相对于源文件的映射物理文件路径。  MemberwiseClone(从 Object 继承) 创建当前 Object 的浅表副本。  OnBubbleEvent 确定服务器控件的事件是否沿页的 UI 服务器控件层次结构向上传递。  OnDataBinding 引发 DataBinding 事件。  OnInit 引发 Init 事件。  OnLoad 引发 Load 事件。  OnPreRender 引发 PreRender 事件。  OnUnload 引发 Unload 事件。 注意   在服务器控件生存期的此阶段,服务器控件应执行所有最后的清理操作,例如关闭文件、关闭数据库连接和丢弃对象。  RaiseBubbleEvent 将所有事件源及其信息分配给控件的父级。  Render 将服务器控件内容发送到提供的 HtmlTextWriter 对象,此对象编写将在客户端呈现的内容。  RenderChildren 将服务器控件子级的内容输出到提供的 HtmlTextWriter 对象,此对象编写将在客户端呈现的内容。  SaveViewState 保存自页回发到服务器后发生的任何服务器控件视图状态更改。  TrackViewState 导致跟踪服务器控件的视图状态的更改,以便这些更改可以存储到服务器控件的 StateBag 对象中。通过 Control.ViewState 属性可访问此对象。 这里我们要重写Render方法,通过HtmlTextWriter 对象将控件中的内容显示出去。 Codenamespace SelfWebControl{publicclass ControlA:Control//Control类中定义了所有ASP.NET服务器控件共享的属性和方法    {protectedoverridevoid Render(HtmlTextWriter writer)        {            writer.Write("<table style='width:300px; height:200px; background-color:Bisque'>");            writer.Write("<tr>");            writer.Write("<td>这是第一列</td>");            writer.Write("<td>这是第二列</td>");            writer.Write("<td>这是第三列</td>");            writer.Write("</tr>");            writer.Write("</table>");        }    }} 生成我们得SelfWebControl工程,再切换到ASP.NET应用程序的工具箱时,VS2008会自动的将我们刚刚创建的ControlA添加到工具箱中,避免了我们以前通过选择项添加控件的过程。 这样,我们就已最简单的形式实现了一个ASP.NET服务器控件。但是如果我想修改表格的宽度,高度,背景色该怎么改呢? 这就需要我们定义服务器控件的属性。大家也都知道,ASP.NET的服务器控件有很多属性,而我们现在的控件只有公有的几个属性。 先来看看我们做了那些改动: Codepublicclass ControlA:Control//Control类中定义了所有ASP.NET服务器控件共享的属性和方法    {privateint _tWidth;privateint _tHeight;privatestring _bgColor;         [Browsable(true)]//在属性窗口中是否可见        [Category("Appearance")]//属性的分类,如,行为,外观,大家可以在属性窗口看见这样的分类        [DefaultValue(100)]//属性的默认值        [Description("表格宽度")]//这些是显示在属性窗口底下的publicint tWidth        {get { return _tWidth; }set { _tWidth = value; }        }         [Browsable(true)]        [Category("Appearance")]        [DefaultValue(100)]        [Description("表格高度")]publicint tHeight        {get { return _tHeight; }set { _tHeight = value; }        }         [Browsable(true)]        [Category("Appearance")]        [DefaultValue("Bisque")]        [Description("表格背景颜色")]publicstring bgColor        {get { return _bgColor; }set { _bgColor = value; }        } protectedoverridevoid Render(HtmlTextWriter writer)        {            writer.Write("<table style='width:"+ tWidth +"px; height:"+tHeight+"px; background-color:"+bgColor+"'>");            writer.Write("<tr>");            writer.Write("<td>这是第一列</td>");            writer.Write("<td>这是第二列</td>");            writer.Write("<td>这是第三列</td>");            writer.Write("</tr>");            writer.Write("</table>");        }    } 代码很简单,想必大家都能看懂,值得注意的就是对每一个属性的声明。需要引用命名空间:using System.ComponentModel;每一个标签的作用我已经在代码中做了说明,这样我们就为我们得控件添加了属性. 还要说明一点的就是,如果我们想在把控件拖到页面中时标签内自动的添加一些属性,需要添加下面的代码: [ToolboxData("<{0}:ControlA runat='server' bgColor='red' tHeight='200' tWidth='300'></{0}:ControlA>")] 值得注意的是这里的写法,{0}的冒号中之后的那个"ControlA“就是类的名字,不要写错。还有runat='sever'一定要写。 是不是很简单,这样,我们只是封装了简单的html来完成ASP.NET控件的制作。 小结:简单的制作一个ASP.NET的服务器控件很简单,但是光只是通过html的输出有的时候意义不大,这里只是介绍一种方法和思路。打开学习定制自己的ASP.NET控件的第一扇门。在以后的文章中我会介绍针对于继承WebControl开发ASP.NET控件。 转自:http://www.cnblogs.com/gaoweipeng/archive/2009/06/13/1501833.html

龙生   08 Apr 2013
View Details

开发者看过来,哪个移动平台好赚钱?

iOS、Android、Windows Phone,各移动平台的盈利情况如何?Visionmobile 网站采访了 3400 多个应用开发者,并进行了深入的数据分析,得出不少值得关注的结论。下面是一些图表。 北美开发者仍然处于领先地位 北美开发者的收入超出欧洲开发者 30%,而欧洲开发者超出亚洲开发者 47%。 北美开发者收入高的原因是:消费者付费更多,iOS 渗透率更高。 平均来看,亚洲开发者开发的应用更多,涉及的平台更多,但收入较低。其原因是:在亚洲多数地区,收费应用不受欢迎,因此亚洲开发者多依赖广告收入,这是最差的盈利模式。 iOS 盈利仍高于其它平台 从单个应用的月收入来看: iOS 平台比 Android 平台的收入高出 30%。相比去年,两者之间的差距降了 5 个百分点。 Windows Phone 比 Android 高出 5 个百分点,这可能有误差,但是去年的数据是 Windows Phone 平台收入只有 Android 的一半。因此,Windows Phone 的盈利水平明显提高了。 跨平台开发者盈利更多 与跨 5 个平台(或更少)的开发者相比,跨 6 个以上平台的开发者收入高出 75%。但是需要注意的是,只有 4% 的开发者为 6 个以上的平台开发,这可能是一些应用较广的服务,比如 Facebook、Skype 等,或者其它一些大软件公司。 只为一个平台做开发的开发者可能是个人或业余开发团队。当他们获得更大成功后,就会扩展到更多的平台。 扩展到更多平台并不足以产生更多利润,但是成功的开发者更乐意采取多平台策略。 扩展新市场是个盈利策略 50% 的开发者会开发自己想用的应用,但这是最不成功的策略。在考虑下一个应用的时候,这不应该是唯一的决定因素。 相比那些只开发自己想用的应用的开发者,做过市场调查(与用户交流、监控应用商店、雇人做调查)的开发者收入更高,是前者的两倍。 开发者中做市场调查的不多,只有 24% 的开发者会与用户交流。 最赚钱的盈利模式是多数开发者无法采用的 设备特许使用费和授权许可费是最赚钱的模式,但是它们的门槛太高,多数开发者无法采用。 其次是委托开发的应用。这种模式风险低,而且收入有保证。 然后是订阅模式。这需要在授权上进行大量投资,而且要维持高质量内容和服务。 对于开发者来说,最受欢迎、最易使用的模式是应用内付款,平均来看,它比 Freemium 模式收入高出 34%,比一次性支付高出 43%。 应用内付款和 Freemium 模式的受欢迎程度在增长,1/4 的开发者使用这两种收入模式。 聪明的开发者使用聪明的工具 使用崩溃报告和 bug 追踪工具的开发者,比不使用此类工具的开发者的收入高出 3 倍。 使用用户分析服务的开发者,比不使用此类服务的开发者的收入高出 168%。 转自:http://www.oschina.net/news/39356/which-apps-make-more-money

龙生   08 Apr 2013
View Details

[EntLib]微软企业库5.0 学习之路——扩展学习篇、库中的依赖关系注入(重构 Microsoft Enterprise Library)

在过去几年中,依赖关系注入 (DI) 模式在 .NET 开发人员社区一直受到关注。长时间以来,优秀的博客作者们讨论着 DI 的优点。MSDN 杂志 针对这一主题发表了多篇文章。.NET 4.0 将发布某种类似 DI 的功能,并计划以后将其发展为完整的 DI 系统。 阅读有关 DI 的博客文章时,我注意到,这一主题有一个很小却很重要的倾向。作者们谈论的是如何在整个应用程序环境中使用 DI。但如何编写使用 DI 的库或框架呢?关注重点的变化,对模式的使用有何影响?这是几个月前我们研究 Enterprise Library 5.0 的体系结构时首先遇到的问题。 背景 Microsoft Enterprise Library (Entlib) 是 Microsoft 模式与实施方案组开发的著名版本。迄今为止,其下载次数已超过两百万。可以想到的单位 — 从金融机构、政府机关到餐厅和医疗设备制造商 — 都在使用它。顾名思义,Entlib 是一种库,可帮助开发人员处理许多企业开发人员都会面临的问题。如果您不熟悉 Entlib,请访问我们的网站 p&p 开发中心,以了解更多信息。 Entlib 在很大程度上由配置驱动。它的大部分代码专用于读取配置,然后基于配置组合对象图。Entlib 对象可能非常复杂。大多数块都包含大量可选功能。此外,还有许多用于支持检测等功能的底层基础结构,它们也需要进行关联。我们不希望用户仅仅为了使用 Entlib 而去手动创建检测提供程序、读取配置,等等,所以将对象的创建封装在了工厂对象和静态外层之后。 Entlib 版本 2 到版本 4 的核心是一个名为“ObjectBuilder”的小型框架。ObjectBuilder 的作者将 ObjectBuilder 描述为“一种用于构建依赖关系注入容器的框架”。Enterprise Library 只是使用 ObjectBuilder 的 p&p 项目之一;其他使用 ObjectBuilder 的 p&p 项目包括 Composite UI Application Block、Smart Client Software Factory 和 Web Client Software Factory。Entlib 特别注重说明的“框架”部分,将一个很大的自定义功能集构建至 ObjectBuilder。读取 Entlib 配置和组合对象图时,需要使用这些自定义功能。在很多情况下,也需要用它们来改进现有 ObjectBuilder 实现的性能。 缺点在于,需要不少时间才能对 ObjectBuilder 本身(设计极为抽象,再加上完全没有文档,ObjectBuilder 的复杂性绝非虚言)和 Entlib […]

龙生   07 Apr 2013
View Details

[EntLib]微软企业库5.0 学习之路——第十步、使用Unity解耦你的系统—PART4——Unity&PIAB

     在前面几篇有关Unity学习的文章中,我对Unity的一些常用功能进行介绍,包括:Unity的基本知识、管理对象之间的关系、生命周期、依赖注入等,今天则是要介绍Unity的另外一个重要功能——拦截(Interception)。 以下是本文所要介绍的内容: 1、Unity与PIAB的关系。 2、使用Unity来接管PIAB的功能实现。 一、Unity与PIAB的关系      Unity中的Interception可以通过Unity的Container或独立的API(Intercept)来实现,这些具体的实现没有包含在Unity本身的类库中,而独立放在Unity.Interception这个类库中,想深入了解的朋友可以查看下这个类的具体源代码。今天介绍的则是Unity与企业库内置的PolicyInjection模块的使用。      在我看来,PolicyInjection就像是Unity.Interception模块的一个通用封装,在PIAB中包含了各种常用的MatchRules(匹配规则)与CallHandler(调用处理程序),其中各种CallHandler都是实现Unity.InterceptionExtension.ICallHandler,而ICallHandler其定义与Unity.InterceptionExtension.IInterceptionBehavior类似的。所以由于PIAB中已经内置好了各种常用的功能,我们只需按照我们的需求调用既可(可参看:内置Call Handler介绍和自定义Matching Rule),如果需要有特殊的逻辑也只需自己定义具体的CallHandler既可(可参看:建立自定义Call Handler实现用户操作日志记录),当然这些都是建立在PIAB的基础上的,如果你不想通过PIAB来实现AOP拦截处理的话,你就可以直接实现Unity中的IInterceptionBehavior来进行具体的业务处理,这个在后面的文章中会介绍到。       其实查看过PIAB模块源码的朋友就可以发现,其实PIAB本质上都是依赖于Unity.Interception模块,其本身没有具体的实现,其具体实现都包含在Unity.Interception.PolicyInjection下(包括MatchRules与CallHandler),有兴趣的朋友可以查看下。由于PIAB依赖于Unity.Interception,所以我们完全可以通过Unity来接管原有PIAB的所有功能(包括各种配置信息)。 二、使用Unity来接管PIAB的功能实现      在建立自定义Call Handler实现用户操作日志记录一文中我已经实现好了一个自定义的CallHandler(如不了解可以先查看下PIAB相关的文章),不过表示层的具体调用还是通过PIAB的PolicyInjection.Create来获取具体对象,而现在我就要通过Unity来接管原来PIAB的这些对象创建,这样极大程度的统一了对象创建与依赖管理。 我这边还是通过代码及配置2种方式来实现Unity接管PIAB的功能,首先是代码的形式,代码配置相对来说比较繁琐,见如下代码:

在底层不变的情况下,表示层如果想通过Unity来实现需要以上的代码配置。虽然配置较为繁琐,但是Unity很好的接管了PIAB的功能同时很大程度的解决了代码之间的耦合关系,其中有3个注意点: 1、创建Unity的container容器时需要增加Interception扩展:.AddNewExtension<Interception>(); 2、在增加策略是需要为需要拦截的接口增加拦截器:SetDefaultInterceptorFor<IStudentManage>(new TransparentProxyInterceptor()) 3、如果MatchRule或CallHandler有相应的构造函数需要通过InjectionConstructor类来初始化构造函数。 接下来是配置文件的代码,如下代码:

读取配置程序代码如下:

可以看到配置文件代码相对来说也不少,但是对于项目使用来说还是偏向于通过配置来解决代码的耦合问题,而且Unity的XSD提供了很好的智能提示,保证了书写配置文件效率及正确性,而且通过将这种具体的关联移到配置文件中也可以大大的减少程序代码的书写,程序代码只需要一句简单初始化+读取配置节既可完成。 配置方式实现的注意点和代码实现类似,我已经写在上面的配置文件中了,其效果和代码配置是一样的。 以上就是本文的所有内容了,仅仅介绍了如何通过Unity来接管PIAB的工作,我这边举的例子是依赖于我原先自己创建的CallHandler,内置的CallHandler配置也是类似的,这边就不再详细介绍了,想了解的朋友还是去查看Unity的官方文档。 有关Unity的拦截技术点可以查看官方文档:Unity Interception Techniques 源代码下载:点我下载 转自:http://www.cnblogs.com/kyo-yo/archive/2010/12/08/Learning-EntLib-Tenth-Decoupling-Your-System-Using-The-Unity-PART3-Unity-And-PIAB.html

龙生   07 Apr 2013
View Details
1 162 163 164 185