[转]Custom Controls in Visual C# .NET-如何实现自定义控件
A very simple introduction to writing your first .NET control
Introduction
This is an extremely simple introduction to creating a control, adding methods and properties, and adding event handlers.
There are two types of components, Visible components (such as a edit box, list control) and non-visible (such as timers, communication, and data access).
This article will concentrate on the creation of a visible component, however the concepts do apply to non visible controls as well.
Visible Components
A visible component is any class derived from either System.WinForms.Control
orSystem.WinForms.RichControl
.
Here is the minimum code to produce the most basic visible control that functions correctly (but doesn't actually doanything).
//specify the namespace in which the control resides
namespace Test.Control
{
//specify the name spaces of other classes that are commonly referenced
using System.WinForms; //the control definition and implementation
public class MyControl : System.WinForms.RichControl
{
}
}
Now, if you ask me, this is a lot more straight forward than any OCX control I have ever written (ATL or not).
The control above, since it is derived from RichControl
, contains quite a bit of stock functionality including: stock properties, stock events, layout management, the ability to act as a full control container (for child controls), and more. In other words, just start writing in your business logic, all of the grunt work is taken care of.
Since the control has no paint routine - yet - it will only erase its background to its parents background color, so it is not too useful at this point. Adding a simple paint routine is also quite simple.
using System.Drawing; protected override void OnPaint(PaintEventArgs pe)
{
SolidBrush b = new SolidBrush(this.BackColor);
pe.Graphics.FillRectangle(b,this.ClientRectangle);
}
The code above will paint the control using its BackColor
property. So if you add this control to a form now and modify its BackColor
propery via the property sheet the control's color will now change as well.
Notice that using System.Drawing;
has been added. This allows classes such as SolidBrush
to be used without specifying the entire namespace (System.Drawing.SolidBrush
).
Adding a property
Adding a read/write or read only property to a control is also quite straight forward. In this example I am going to add a set of gradient color properties to the control. Below I am only going to show one of the properties, since the other is a mirror copy of the first, except for the variable name.
private System.Drawing.Color gradColor1; public System.Drawing.Color Gradient1
{
set
{
this.gradColor1 = value;
}
get
{
return this.gradColor1;
}
}
So, first I must add a data member to hold the properties value. Since the property is a color it will be of typeSystem.Drawing.Color
. Since using System.Drawing;
has been added the variable can also be declared as just Color
.
Next the declaration for the Gradient1
property is made. The start of the declaration looks similar to a function declaration (access modifier, return type, and name). Although the property itself is not a function it can contain two special functions nested within it: set
and get
. To make a read/write property both set
and get
must be implemented. For a read-only property just implement get
. Even though the set
function does not have a parameter list, it does get passed a special parameter called value
. The type of the Value
parameter will always be the same type as the property itself.
Since properties are set and retrieved indirectly (which is quite different from reading and writing to data members), other code can be added to the set
and get
functions. For instance if a property is a calculated value, the calculation can be performed within the get
itself. During a set
it is possible to set flags or cause the control to refresh itself, etc.
To make a control easy to use during design time, many controls group their properties and have help strings that display when the property is selected in the property browser. This can also be easily accomplished through the use of attributes. Attributes are special objects that are added above the declaration of a class, function, enum or property, and are delimited by ‘[‘ and ‘]’.
[
Category("Gradient"),
Description("First Gradient Color")
]
public System.Drawing.Color Gradient1
{
set
{
this.gradColor1 = value;
}
get
{
return this.gradColor1;
}
}
The attributes above cause this property to show up in a Gradient
property group and will display "First Gradient Color" as a help string at the bottom of the property browser when selected.
Adding a method
Adding a method is the same as adding any other function. In fact a function and method are essentially the same in the .Net world. If you do not want the function exposed to the outside just make sure its access modifier is set to protected or private. This is not to say that all your public functions can be used by anyone, you have quite a bit of control over the use of your functions … but that is another topic.
public void StartRotation(bool state)
{
...
}
In this example the function StartRotation
will be added, which will rotate the angle of the gradient based on a timer.
private System.Timers.Timer rotateTimer = null; public void StartRotation(bool state)
{
rotateTimer = new System.Timers.Timer();
rotateTimer.Tick += new EventHandler(OnTimedEvent);
rotateTimer.Interval= ;
rotateTimer.Enabled = true;
} public void OnTimedEvent(object source, EventArgs e)
{
gradAngle += ;
if(gradAngle > = )
{
gradAngle = ;
}
this.Refresh();
}
Since the timer class fires an event, you will notice the code required to use an event is quite basic, however I will explain how events work later on.
When the event fires it will call the specified function, this is where the angle is updated and a Refresh
is requested.
Using and Adding Events
In the previous section code was added that used a timer event.
rotateTimer.Tick += new EventHandler(OnTimedEvent);
The Timer class has an event member called Tick
that handles a list of event listeners. Since an event can have more than one listener the +=
is used to assign the event.
So to tell the timer to call the event handler OnTimedEvent
just create a new event handler, pass in the function name into the constructor and assign that to the Timers event list. Any number of event handlers can be added to a single event. Note, the order in which the handlers are called is not defined.
To create your own event here is what to do.
First declare the interface of the event (its required parameters and return type), then make an instance of this type. Note the use of delegate
.
public delegate void angleChange();
public event angleChange OnAngleChange;
The code above adds an event list OnAngleChange
that can be used to add an event in the following manner
MyControl ctrl = new MyControl();
ctrl.OnAngleChange += new MyControl.angleChange(OnMyEvent); public void OnMyEvent()
{
MessageBox.Show("Event Fired");
}
To actually fire an event you need to first check that your event is non-null, and then fire the event using the following:
if (OnAngleChange != null)
{
OnAngleChange();
}
Simple! So now you have your first control that has methods, properties and events.
The complete source code is below:
//specify the namespace in which the control resides
namespace Test.Control
{
//specify the name spaces of other classes that are commonly referenced
using System;
using System.Collections;
using System.Core;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Data;
using System.WinForms;
using System.Timers; //the control definition and implementation
public class MyControl : System.WinForms.RichControl
{
private System.Drawing.Color gradColor1;
private System.Drawing.Color gradColor2;
private int gradAngle = ; private System.Timers.Timer rotateTimer = null; public delegate void angleChange();
public event angleChange OnAngleChange; private void InitializeComponent ()
{
} public MyControl()
{
InitializeComponent(); } protected override void OnPaint(PaintEventArgs pe)
{
LinearGradientBrush b = new LinearGradientBrush(this.ClientRectangle,
gradColor1, gradColor2,gradAngle,false); pe.Graphics.FillRectangle(b,this.ClientRectangle);
} public void StartRotation(bool state)
{ rotateTimer = new System.Timers.Timer();
rotateTimer.Tick += new EventHandler(OnTimedEvent);
// Set the Interval to 5 seconds.
rotateTimer.Interval=;
rotateTimer.Enabled=true; } public void OnTimedEvent(object source, EventArgs e)
{
gradAngle += ;
if(gradAngle >= )
{
gradAngle = ;
}
this.Refresh(); if(OnAngleChange != null)
{
OnAngleChange();
}
} [
Category("Gradient"),
Description("First Gradient Color")
]
public System.Drawing.Color Gradient1
{
set
{
this.gradColor1 = value;
}
get
{
return this.gradColor1;
}
} [
Category("Gradient"),
Description("Second Gradient Color")
]
public System.Drawing.Color Gradient2
{
set
{
this.gradColor2 = value;
}
get
{
return this.gradColor2;
}
}
}
}
原文连接:着重推荐,仔细学习。
http://www.codeproject.com/Articles/837/Your-first-C-control
http://www.akadia.com/services/dotnet_user_controls.html#Login%20Validation%20User%20Control
[转]Custom Controls in Visual C# .NET-如何实现自定义控件的更多相关文章
- SharePoint Development - Custom List using Visual Studio 2010 based SharePoint 2010
博客地址 http://blog.csdn.net/foxdave 之前两次我们定义了内容类型和字段,我们现在用它们为这一讲服务--创建一个自定义列表. 打开Visual Studio,打开之前的工程 ...
- SharePoint Development - Custom Field using Visual Studio 2010 based SharePoint 2010
博客地址 http://blog.csdn.net/foxdave 自定义列表的时候有时候需要自定义一些字段来更好地实现列表的功能,本文讲述自定义字段的一般步骤 打开Visual Studio,我们还 ...
- [XAF] Simplifying integration of custom controls bound to data from XAF application database
ASP.NET: http://www.screencast.com/t/OHhcHD9vy WinForms: http://www.screencast.com/t/8M8K4eskkYO9
- c# Custom Controls
http://www.cnblogs.com/light169/archive/2008/06/11/1217139.html
- (转) [it-ebooks]电子书列表
[it-ebooks]电子书列表 [2014]: Learning Objective-C by Developing iPhone Games || Leverage Xcode and Obj ...
- [转] 基于C#的波形显示控件的实现
转自 基于C#的波形显示控件的实现[附完整源码下载] 编者记: 09年暑假正好在学院实验室呆了一段时间,做了个完整的上位机软件(具体实现:根据下位机的指令,实现通过串口来操纵下位机进行实验,并将采集的 ...
- [百度网盘]Xamarin for Visual Studio 3.7.165 Preview 最新版-介绍
Xamarin 3.7.165 Preview 下载地址:http://download.xamarin.com/XamarinforVisualStudio/Windows/Xamarin.Visu ...
- Build 2017 Revisited: .NET, XAML, Visual Studio
For the next couple months we're going to revisit Build 2017, each post focusing on different aspect ...
- Writing a Reusable Custom Control in WPF
In my previous post, I have already defined how you can inherit from an existing control and define ...
随机推荐
- leetcode字符串系列
3. 无重复字符的最长子串 给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度. 示例 1: 输入: "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串 ...
- 关于HTML框架(frameset)的一些基本用法
frameset 定义 W3C是这样定义frameset框架的,通过使用框架,你可以在同一个浏览器窗口中显示不止一个页面.每份HTML文档称为一个框架,并且每个框架都独立于其他的框架.注意,这是HTM ...
- JS 正则截取字符串
1.js截取两个字符串之间的内容: varstr = "aaabbbcccdddeeefff"; str = str.match(/aaa(\S*)fff/)[1]; alert( ...
- sublime3 常用快捷键
轻量级编辑器,一直用的sublime text3 , 可以根据自己喜好安装喜欢的风格插件,根据工作需求安装代码处理插件. 下一章将推荐我常用的一些风格与代码插件 这里记录一些sublime 常用的快捷 ...
- MySql循环语句
drop procedure if exists test_insert; DELIMITER ;; CREATE PROCEDURE test_insert () BEGIN DECLARE i I ...
- centos7下采用Nginx+uwsgi来部署django
之前写过采用Apache和mod_wsgi部署django,因为项目需要,并且想比较一下Nginx和Apache的性能,尝试采用Nginx+uwsgi的模式来部署django. 1.安装uwsgi以及 ...
- 安装ArcGIS Enterprise WebGIS (Portal ArcGIS Server DataStore ) 系统后如何应对网络环境的配置修改
客户往往在部署完ArcGIS WebGIS系统后,由于需要满足业务或者网络管理的要求,需要修改系统的网络环境的配置,下文将从常见的几个场景来讲述如何去应对这些变动. 1.网络IP地址变动 由于在部署W ...
- 如何通过活字格实现Excel 汇总
企业中,经常面临需要汇总大批量的Excel 数据表的需求.如果仅通过手工汇总,则会有非常大的工作量,而且还很容易出现错误.此时,如果可以借助活字格这样的工具,来帮助实现汇总Excel 的功能,则会使工 ...
- Adapter中用不了getWindowManager()
在写popupwindow的时候一般会获取屏幕的宽高来设置popupwindow的宽高,但是在adapter中用不了getWindowManager(), 但是为什么Activity中就可以用getW ...
- JNI使用方法
JNI可以让我们在java代码中调用本地库的功能. 下面记录一下JNI简单的使用方法 创建java端接口 public class JNIIterface { // 导入最终生成的dll文件 stat ...