خیلی وقت بود که میخواستم تجربیاتم رو تو این زمینه در اختیار دیگر برنامه نویس ها قرار بدم . خوشبختانه فرصتی پیش اومد و تا این مطالب را من گرد آوری کنم . من با تعریف یک sample کار خود رو شروع میکنیم .
خوب حالا چی میخوایم بنویسیم :
خوب این کنترل ما قراره وقتی به فرم اضافه میشه به تمام text box های برنامه 2 خاصیت به نام ISRequired و ValidationPatern اضافه کند .
خوب شروع کنیم .
اول vs تون باز کنید .
بعد یک پروژه از نوع Class Library اضافه کنید . اسمشم هر چی دوست داشتی بزار من گزاشتم H128Control
بعد یه کلاس به نام ValidationControl به پروژتون اضافه کنید .
خوب ابتدا این name space ها را به class تون add کنید .
using system.text.regularexpressions;
using system;
using system.componentmodel;
using system.windows.forms;
using system.collection ;

خوب refrence هاشم خودتون ok کنید .
بریم سر قسمت بعد .
معمولا کنترل ها به 2 گونه هستند : 1 - کنترل هایی که کنترل های دیگر را extend میکنند مثل کنترلی که ما داریم مینویسیم (errorprovider,tooltip,...( و دیگری خود کنترل مانند ,...textbox ,button هستند

خوب بریم سر کنترل خودمون :
به کلاسمون بگیم از component ,iextenderprovider به ارث ببرد برای این کار :
public class validationcontrol : component,iextenderprovider
وقتی که iextenderprovider اضافه کردین باید یک متد به نام canextend هم بهش اضافه کنید فکر کنم tab بزنید خودش اضافه کنه نمیدونم الان C#‎ باز نیست به هر حال :
public bool CanExtend(object sender)
{
return object is textbox;
}

در واقع این متد به ما میگه شما چی رو دارین توسعه میدین که من بهش گفتم textbox

خوب بریم سراغ قسمت بعدی :
برای اینکه کنترل ما بتونه از چند تا textbox پشتیبانی کنه احتیاج به یک کلاس و یک collection که بتونیم کلاس مورد نظر رو پیدا کنیم که من اینجا به خاطر سرعت بیشتر از hashtable استفاده کردم .

خوب اول hashtable مون ردیف میکنم بعد میریم سراغ کلاسه :
hashtable extendtable;

و تو کانستراکتورمون اونو new میکنیم .
public validationcontrol ()
{
extendtable=new hashtable();
}


یه کلاسه دیگه به برنامتون اضافه کنید به نام validation class و توش 2 تا پروپرتی به نام ISRequired,ValidationPatern بدین شکل تعریف کنید :
private class validationclass
{
private bool isrequired=false;
private string validationpatern=string.empty ;

public bool ISRequired
{
get
{
return isrequired;
}
set
{
isrequired=value;
}

public string ValidationPatern
}
get
{
return validationpatern;
}
set
{
if (validationpatern!=value)
validationpatern=value;
}
}
}


خوب دوباره بریم تو کلاس اصلی کار manage پروپرتی ها رو ردیف کنیم .

حتما شما کنترل errorprovider دیدین یادتون چجوری باهاش کار میکردیم .
errorprovider.seterror(controlname control,string value)


پس کنترل ما نیز به 2 متد set,get نیاز دارد .
یکی برای ISRequred , دیگری ValidationPatern
پس چرا معطلین شروع کنید به نوشتن میگین چه جوری خوب به این شکل :
Public Void SetISRequired(control mycontrol,bool Value)
{
validationclass myvalidation;
if (tableextend.containskey(control)
{
myvalidation=(validationclass)tableextend[mycontrol];
}
else
{
myvalidation=new validationclass();
}
myvalidation.ISReqired=Value;
mycontrol.Validation+=new canceleventhandler(mycontrol_validating);
if (!tableextend.containkey(mycontrol)
tableextend.add(mycontrol,myvalidation);
}

خوب این متد set ش .
خوب یه توضیح راجبش بدم :
خوب اولش به کلاس validationclass متغیر myvalidation بهش assign کردم .
بعد گفتم اگر تو hashtable هم نیود ازش یه شی جدید میسازم و اگرنه خودتون میبینید .
بعد به مقدار required هم مقدار دهی کردم .
بعد به کنترل textbox طرف event validating رو بهش اضافه کردم .
در آخرم گفتم اگر تو hashtable هم نبود شی که از کلاسم اضافه کن به hashtable تا برای دفعه بعد گمش نکنم .
شما هم میتونید از struct و هم از کلاس استفاده کنید بازم من باس خاطر سرعت طرف کلاسو گرفتم .
اصلا کلاس یه کلاسه دیگه داره . C#‎ یعنی CLASS و CLASS هم یعنی C#‎!
خوب بریم سراغ getش ببینیم چی میگه :
public bool GetISRequired(control mycontrol)
{
validationclass myvalidation;
if (tableextend.containskey(mycontrol)
{
myvalidation=tableextend[mycontrol];
return myvalidation.ISRequired;
}
return false;
}

برای اون یکی پروپرتی هم همین کارا رو بکنید برای چیزو میگم validationpatern همینجوری است ok اسم متدشم میشه یکیش SetValidationPatern ,GetValidationPatern

خوب اینم میشه کد event validating مون :
private void mycontrol _validating (object sender,canceleventargs e)
{
validationclass myvalidation;
if (tableextend.containskey(sender))
{
myvalidation=(validationclass)tableextend[sender];
if ((textbox)sender).Text.Trim()==string.empty & myvalidation.ISRequred==true )
{
e.cancel=true ;

}
if (myvalidation.validationpatern!=string.empty) & ((textbox)sender).Text.Trim()!=string.empty
{
try
{
Regex regex=new Regex(myvalidation.ValidationPatern );
if (!regex.IsMatch(((TextBox)sender).Text)) e.Cancel =true ; return ;}
catch{throw new Exception("there is a mistake in patern"); }
}
}
}

توضیح : regex که همه فکر کنم میدونید چیه . بقیشم نکته خاصی نداره .
قسمت آخرشم میشه :
قبل از تعریف کلاسمون این attribute ها را اضافه میکنیم .
[ProvideProperty("ISRequired",typeof(TextBox ))]
[ProvideProperty("ValidationPatern",typeof(TextBox ))]


همین دیگه تموم شد .