PDA

View Full Version : سوال: چگونگی ساختار نوشتن یک Event ؟



cs_mz88
شنبه 27 اسفند 1390, 10:13 صبح
سلام.
اگه ممکن است یک نفر توضیح کامل درباره Eventها برای دوستام و من بنویسه .
من یکی دوتا مقاله خوندم اما نفهمیدم کجا ها نیاز داریم ما خودمون Event بنویسیم.و حتی چطور بنویسیم.
در کنار این با delegetها هم این مشکل رو دارم،چون با Event ها در ارتباطن.
متشکرم از لطفتون:خجالت:

cs_mz88
یک شنبه 28 اسفند 1390, 13:10 عصر
واقعا کسی از این مبحث خبری نداره؟

Arash_janusV3
یک شنبه 28 اسفند 1390, 14:24 عصر
اگر می شه اون تعریفی که خودت از event می دونی را بگو
یعنی راجب event چیا می دونی؟

be_kh
یک شنبه 28 اسفند 1390, 18:40 عصر
سلام
یا توجه به معنیه واژه یعنی رخداد، شما زمانی که می خواین اتفاقی رو به کاربر اعلام کنید (کاربر میتونه خود برنامه نویس باشه در حین نوشت کد از همان رخداد استفاده کنه) از رخداد ها استفاده می کنید. به عنوان مثال میگین وقتی عمل افزودن رکورد در بانک اطلاعاتی با موفقیت انجام شد عمل نامشخصی رو انجام بده، عمل نامشخص در واقع عملیاتی هستش که میتونه موجود باشه یا نباشه خب شما میاین شی کلاس رخداد را بعد از اتمام عملیات اجرا می کنید اگر رخداد دارای متد اجرایی بود که دستورات درون متد نسبت داده شده به رخداد اجرا میشه در غیر این صورت خیر و روال عادی خودش رو در هر حالتی پیش میگیره.
اگر خودتون هم ببینید رخداد کلیک بعد از فشردن کلید اتفاق باشه حالا اگر دستوری باشه که اجرا میشه و اگر نه که اجرا نمیشه، شرط اجرا وجود متد کلیک انتساب داده شده به رخداد کلیک اون شی هستش
امیدوارم مفید واقع شده باشه

lvlaziar
یک شنبه 28 اسفند 1390, 21:59 عصر
با تشکر!
اینجا هم توضیحات خوبی ( البته به زبانه شیرین اصلی :لبخند: ) داده شده:
http://msdn.microsoft.com/en-us/library/aa645739(v=vs.71).aspx
هم در مورد event ها هم deleget :لبخندساده:

cs_mz88
یک شنبه 28 اسفند 1390, 23:57 عصر
ممنونم دوست من.
ولی از نوع ساختارش چیزی نگفتی، اگه میشه از طرز نوشتن،انواع اون و ...
توضیح بدید

AlgorithmX
شنبه 05 فروردین 1391, 18:33 عصر
ممنونم دوست من.
ولی از نوع ساختارش چیزی نگفتی، اگه میشه از طرز نوشتن،انواع اون و ...
توضیح بدید

گلم نوع نوشتن رویدادها به دو صورته (البته یکی!)

1- نوع اولش از طریق انتخاب یه کنترل و رفتن به تب رویدادها اون کنترله مثل عکس زیر :
84625
وانتخاب رویداد مورد نظرت! مثل MouseDown(موقعی که موس روکنترلت پایین نگه داشته میشه) ، MouseMove(موقعی که موس روکنترلتبه حرکت درمیاد)، MouseClick(موقعی که روی کنترلت کلیک میشه) ، و خیلی رویدادهای دیگه که میتونی خودت ببینی و روش دابل کلیک کنی تابتونی براشی رویداد مورد نظرت برنامه بنویسی!

2- انجام کاربالا (انتخاب نوع رویداد) به صورت کد نویسی (که اونم برای کنترل هاییه که ممکنه در هنگام اجرا (runtime) خودت بسازی). که آموش هاش توسایت هست، اگرهم درست چیزی نفهمیدی ازشون سوال بپرس من جواب میدم!!

asadegha
یک شنبه 06 فروردین 1391, 04:59 صبح
وقتی میخوای خودت رویداد بنویسی اول باید مشخص کنی که برای چه رویدادی داری مینویسی. فرضا Click یا keydown.
حالا با توجه به این نوع و تعداد پارامتر رویدادی که داری مینویسی باید با نوع و تعداد رویداد مورد نظرت یکی باشه.

گاهی میای یه کلاس مینویسی فرضا برای بازی. میای از طریق کد نویسی توی کلاست فرم ایجاد میکنی که مثلا زمین بازیته. حالا میخوای به فرمت رویداد form_load اضافه کنی. چون این فرم در زمانه کد نویسی ایجاد میشه پس نمیتونی از طریق گفته شده در بالا (تب Properties) تعیین کنی و form_load رو انتخاب کنی و کد بنویسی براش. بنابراین نیاز داری خودت جداگانه یه رویداد بنویسی.(اینجاست که به نوع و تعداد پارامتر باید دقت کنی). حالا بعد از اینکه این رویداد رو نوشتی با یه دستور ساده باید به فرمت بگی که این رویداد مال تو هست و مربوط به Form_load هست. اینطوری:

class Class1
{
private Form frmMain;
public Class1()
{
frmMain = new Form()
{
Size = new System.Drawing.Size(100, 100)
};
frmMain.Load += new EventHandler(FRM_Load);
}

void FRM_Load(object sender, EventArgs e)
{
//... code haye marbot be form load
}
}

cs_mz88
یک شنبه 06 فروردین 1391, 15:06 عصر
با تشکر زیاد از دوستان.
یه جایی دیدم که از deleget هم استفاده کرد برای نوشتن یک رویداد.
چرا روبروی EventHandler فقط یک پارامتر قرار دادین؟ اون پارامتر چیه؟

cs_mz88
یک شنبه 06 فروردین 1391, 15:07 عصر
دوست من میشه روش دومشو یاد بدی؟ البته با توضیح کامل
ممنون

AlgorithmX
یک شنبه 06 فروردین 1391, 15:37 عصر
دوست من میشه روش دومشو یاد بدی؟ البته با توضیح کامل
ممنون

عزیزم روش دوم همینیه که دوستمون برات نوشت!! (این پایین /\)




class Class1
{
private Form frmMain;
public Class1()
{
frmMain = new Form()
{
Size = new System.Drawing.Size(100, 100)
};
frmMain.Load += new EventHandler(FRM_Load);
}

void FRM_Load(object sender, EventArgs e)
{
//... code haye marbot be form load
}
}





حالا پاسخ این سوال :
با تشکر زیاد از دوستان.
یه جایی دیدم که از deleget هم استفاده کرد برای نوشتن یک رویداد.
چرا روبروی EventHandler فقط یک پارامتر قرار دادین؟ اون پارامتر چیه؟


frmMain.Load += new EventHandler(FRM_Load);
این دستور باعث میشه در زمان وقوع یه رویداد (که در اینجا Load هست) تابعی که در داخل پرانتز نوشته شده فراخوانی بشه (که میشه تابع : FRM_Load ).
حالا این تابع هم که در پایین دوستمون نوشتش!
void FRM_Load(object sender, EventArgs e)
{
//... code haye marbot be form load
}


توجه : هرتابعی رو هم نمیشه برای یک رویداد قرار داد! باید حتماً دو پارامتر object sender, EventArgs e را داشته باشند!!



البته همه اینا رو خوده دوستمون توضیح داده، فقط مجبور به تکرار شدم شاید بهتر درک بشه!!

رافعی مهدی
یک شنبه 06 فروردین 1391, 18:09 عصر
با اجازه دوستان یک روش دیگر هم بنده معرفی کنم که فکر میکنم پاسخ این جمله باشه که:

یه جایی دیدم که از deleget هم «میشه» استفاده کرد برای نوشتن یک رویداد.

در این روش یک رخداد (Event) رو به شکل ضمنی در یک Scope تعریف میکنیم.[1] این روش مزیت خاصی نداره و بیشتر باعث میشه تا کد حالت اسپاگتی به خودش بگیره و فقط میشه گفت یه جور ساده نویسی محسوب میشه. (برای اطلاعات بیشتر اینجا (http://stackoverflow.com/questions/10006041/whats-the-benefits-of-registering-an-event-handler-implicitly/10006104#comment12791833_10006104) رو ببینید.)، برای مثال فرض کنید در Scope یک متد بخواهیم یک رخداد رو رجیستر کنیم.


private void MyMethod()
{
button1.Click += delegate(object sender, EventArgs e)
{

};
}


نکته: همانطور که دوستان میدونند در برنامه هایی که اینترفیس گرافیکی داینامیک دارند، گاهی لازم هست رخدادها رو در مواردی Registered و Unregistered کنیم که شکل کلی این کار به صورت زیر هست:


someObject.Event += new SomeDelegate(SomeType1 arg1, SomeType2 arg2, ...);
و


someObject.Event -= new SomeDelegate(PreRegisteredMethodName);

که در اون PreRegisteredMethodName اسم متدی است که پیش از این برای Handle کردن رخداد مورد نظر، Register شده است.

ببینید اینکه دوستمون گفتند:

توجه : هرتابعی رو هم نمیشه برای یک رویداد قرار داد! باید حتماً دو پارامتر object sender, EventArgs e را داشته باشند!!
کلیت نداره! شاید هم برای ساده تر بیان کردن مسئله به این صورت توضیح دادند. به هر حال...

در حقیقت اگر بخواهیم مفهوم delegate رو به شکل ساده توضیح بدهیم باید گفت که delegate ریخت (قالب) یک متد رو تعیین میکنه. بنابراین هنگامی که میخواهیم یک event جدید تعریف کنیم به اون نیازمندیم تا بعداً بدونیم که چه متدهایی میتوانند اون رخداد رو Handle کنند. (البته باز این تنها کاربرد delegate نیست و در Reflection و ... هم ازش استفاده میشه.) مثلاً رخداد پر کاربرد Click مربوط به یک Button رو در نظر بگیرید. این رخداد دارای یک قالب مشخص هست. قالبش رو کی تعیین میکنه؟ اون delegate ای که این رخداد (Click) از جنس اون تعریف شده؛ EventHandler.

برای درک بهتر، Caret رو ببرید روی EventHandler و دکمه F12 رو فشار بدید. وارد صفحه ای میشوید که metadata مربوط به این تعریف رو به شما نشان میده. میبینید که این delegate با چه ریختی تعریف شده:


public delegate void EventHandler(object sender, EventArgs e);

یکی از معانی این تعریف این هست که هر event ای که بخواهد از جنس این delegate تعریف بشه، حتماً باید خروجی void و آرگومانهایی مشابه با اون داشته باشه. یعنی object sender, EventArgs e. این در حالی است که قطعاً تمام eventها از جنس این delegate نیستند. برای نمونه رخداد Paint رو برای یک Button در نظر بگیرید. جنس اون PaintEventHandler هست که ریخت متفاوتی داره. (برای تمرین metadata اون رو نگاه کنید.) حالا باید کاملاً مشخص شده باشه که چرا وقتی رخداد Click یا Paint یک Button رو به یک متد به صورت اتوماتیک (به کمک Visual Studio) نسبت میدهیم، ریخت خاصی به خودشون میگیرند.

________________________________
[1] به طور ساده، Scope به یک محدوده در کد گفته میشود که با { } از سایر بخشهای برنامه جدا شده باشد.

asadegha
دوشنبه 07 فروردین 1391, 01:20 صبح
دوست عزیز جناب مهدی رافعی.

فکر میکنم اگه یکم ساده تر بیان میکردین دوستمون بهتر مطلب رو درک میکردن. البته جسارت نمیکنم. خیلی خوب خلاصه و مفید زحمت توضیحات رو کشیدین. خودم درک کاملا درستی از delegate ندارم. ببینین درست فهمیدم چیه؟ اما:

Delegate در واقع مثل یه متغیر میمونه که آدرس توابع رو میتونه در خودش نگه داره ولی هر تابعی نه. فرمت تابعی(یعنی نوع خروجی و نوع و تعداد پارامتر های تابع) که یه delegate میتونه نگهداری کنه در زمان تعریف delegate تعیین میشه.
public delegate void EventHandler(object sender, EventArgs e);

حالا میتونیم هرنوع تابع با فرمتبندی مشخص شده رو به این Delegate معرفی کرد و در رویدادی از یک شی مثلا button رجیسترش میکنیم.
button1.Click += delegate(btn_Click)

حالا با اجرای رویداد کلیک تابع btn_Click اجرا میشه.

رافعی مهدی
دوشنبه 07 فروردین 1391, 10:14 صبح
این جمله شما که گفتید:

Delegate در واقع مثل یه متغیر میمونه که آدرس توابع رو میتونه در خودش نگه داره ولی هر تابعی نه.
رو چندان باهاش موافق نیستم. delegate میتونه به عنوان آرگومان به یک متد پاس داده بشه، (برای کسب اطلاعات بیشتر اینجا (http://www.functionx.com/csharp2/classes2/delegates2.htm) رو بخونید.) ولی اینکه بگیم خودش یک متغیر هست، نه. از طرفی عبارت آدرس توابع اصلاً عبارت مناسبی در اینجا نبود. ولی جمله بعدی شما که گفتید:

فرمت تابعی(یعنی نوع خروجی و نوع و تعداد پارامتر های تابع) که یه delegate میتونه نگهداری کنه در زمان تعریف delegate تعیین میشه.
جمله کاملاً درستی هست و مخصوصاً چیزی که در پرانتز آوردید عبارت گویا و مفیدی بود. فقط بهتر بود به جای کلمه تابع که معادل Function هست از متد (Method) استفاده کنید. (کلاً این نکته رو در مورد زبانهای تحت Net Framework. عرض میکنم.)
در مجموع delegate چیز اساساً پیچیده ای نیست و به عقیده من اگر اون رو به عنوان ابزار تعریف قالب متد در نظر بگیریم دیگه هیچ ابهامی نباید وجود داشته باشه. گذشته از این بحث، در مورد استفاده از eventها یک نکته دیگه هم به نظرم میرسه که شاید مطرح کردنش در این تاپیک بد نباشه:

به هر eventای که شما متصور بشید، اعم از static event یا instance event، برای اون چیزی که event رو دارید براش به کار میبرید،
خواه خود کلاس باشه (static)،
خواه یک instance) ،object)،
میشه Handlerهای متعددی ثبت کرد و بالعکس؛ میشه eventهای متعددی رو تنها به یک Handler پاس داد.

در واقع، Handler اون متدی است که میخواهد event رو Handle کنه. (باهاش سر و کار داشته باشه و امور مربوط به اون رو به انجام برسونه!) برای همین هم هست که اسم یک delegate معروف رو گذاشتند EventHandler. نه اینکه خود اون delegate بخواهد event رو Handle کنه که delegate یک قالب بیش نیست، بلکه وقتی میخواهیم متدی رو به عنوان مسئول Handle کردن اون event در نظر بگیریم، از این delegate استفاده میکنیم و تأکیدی بر این موضوع ایجاد میشه که فلان متد قرار هست فلان رویداد رو Handle کنه. (« مفهوم مثال زیر:)


this.button1.Click += new System.EventHandler(this.button1_Click);
بدیهیه که در این خط، button1_Click همون متدی است که قراره رویداد Click رو Handle کنه. حالا تصور کنید که در یک فرم 2 تا دکمه داریم که قراره هر دوی اونها یک کار مشترک رو انجام بدهند. (چیزی که علیرغم بعید به نظر رسیدنش در بسیاری از اینترفیسها اتفاق میفته!!!) برای انجام این کار لازم نیست دو تا متد مجزا تعریف کنیم و بی جهت کد تکراری بنویسیم. میشه نوشت:


this.button1.Click += new System.EventHandler(this.buttons_Click);
this.button2.Click += new System.EventHandler(this.buttons_Click);

مشخصاً در این کد متد buttons_Click، رویداد کلیک هر دو دکمه رو Handle میکنه. اصلاً علت اینکه برای Register کردن Handlerها از =+ استفاده میشه هم همینه. (اگر یکتا بود = کفایت میکرد!) از طرفی شما ممکنه برای Handle کردن یک رویداد خاص، از بیش از یک Handler استفاده کنید. مثلاً داشته باشید:


this.button1.Click += new System.EventHandler(this.button1_PartOne_Click);
this.button1.Click += new System.EventHandler(this.button1_PartTwo_Click);

که تحلیل اون رو به عهده خودتون میذارم. (مفهوم متد partial چیست؟)

موفق باشید.

cs_mz88
چهارشنبه 09 فروردین 1391, 11:59 صبح
ممنونم دوست من.
حالا کلا ،کجا باید بفهمیم که الان باید از deleget استفاده کنیم؟
ممنون میشم روشنم کنید

vof.ir
چهارشنبه 09 فروردین 1391, 15:21 عصر
از توضیحات دوستان متشکرم. من هم سوالی برایم پیش آمده، خب فرض کنید حالا زمانی میخواهیم این رویداد را صدا بزنیم، یعنی مثلا وقتی که پراپرتی تعداد کاراکتر یک یوزر کنترل بیش تر از 10 شد یک رویداد به اسم
OverFlowCharLength را صدا بزنیم تا کدی که کاربر درون متدی که به این رویداد وصل شده است، اجرا گردد. این را چگونه هندل کنیم؟

رافعی مهدی
چهارشنبه 09 فروردین 1391, 17:48 عصر
شاید بد نباشه پاسخ هر دو دوست عزیز (cs_mz88 (http://barnamenevis.org/member.php?198034-cs_mz88) و vof.ir (http://barnamenevis.org/member.php?93737-vof.ir)) رو در قالب همون مثال مطرح شده بدهم. فرض کنید یک UserControl داریم که دارای یک پراپرتی هست و مثلاً نام یک شخص رو در خودش نگهداری میکنه:


private string _LastName;
public string LastName
{
get
{
return _LastName;
}
set
{
_LastName = value;

if (value.Length > 10)
{
//
// How to invoke an arbitrary event?
//
}
}
}

ببینید، در اینجا هیچ رویداد پیش فرضی وجود نداره که ما بخواهیم برای این کار از اون استفاده کنیم. بنابراین لازم هست که خودمان یک رویداد جدید تعریف کنیم. اولین سوالی که پیش میاد اینه که وقتی این رویداد جدید اتفاق افتاد، چه اطلاعاتی باید بده؟ آیا صرف اطلاع رسانی کفایت میکنه یا مثلاً میخواهیم وقتی این اتفاق میفته بدونیم قبلاً نام این شخص چی بوده که حالا داره تعداد کاراکترهایش از 10 تا تجاوز میکنه؟ در حقیقت پاسخ به این سوال ما رو قادر به طراحی یک قالب (ریخت) مناسب برای این رویداد میکنه. خب، حالا این قالب رو چطور باید تعیین کنیم؟ طیعتاً با استفاده از یک delegate!


public delegate void CharLengthOverFlowedEventHandler(string oldValue, string newValue);
public event CharLengthOverFlowedEventHandler CharLengthOverFlowed;

نکته 1: در کلاسی که event رو تعریف میکنیم، باید تعیین کنیم که در چه مواقعی این رویداد اصطلاحاً fire بشه، یا به زبان ساده کی اتفاق بیفته؟ برای انجام این کار، بهترین و در عین حال ساده ترین روش استفاده از Snippet ای به نام invoke هست.[1]

بنابراین داریم:


public class MyControl : UserControl
{
public delegate void CharLengthOverFlowedEventHandler(string oldValue, string newValue);
public event CharLengthOverFlowedEventHandler CharLengthOverFlowed;

private string _LastName;
public string LastName
{
get
{
return _LastName;
}
set
{
string oldValue = _LastName;
_LastName = value;

if (value.Length > 10)
{
//
// Raising an arbitrary event..
//
CharLengthOverFlowedEventHandler temp = CharLengthOverFlowed;
if (temp != null)
{
temp(oldValue, value);
}
}
}
}


// Rest of class codes..
}

نکته 2: شرط temp != null به این معناست که اگر فقط در جایی این رویداد Register شده، عملیات Firing صورت بگیره. (شاید شما در محل استفاده از یوزر کنترل خود، از این رویداد استفاده نکرده باشید، درست شبیه به اینکه از یک button استفاده کرده باشیم ولی هنوز رویداد Click آن رو به هیچ متدی برای Handle کردن، نسبت نداده باشیم.)

اکنون نوبت به استفاده از این رویداد میرسه. داریم:


{
MyControl myControl = new MyControl();
myControl.CharLengthOverFlowed += new CharLengthOverFlowedEventHandler(myControl_CharLen gthOverFlowed);

myControl.LastName = "یک نام بزرگ";
}

و

private void myControl_CharLengthOverFlowed(string oldValue, string newValue)
{
//
// ToDo: Treat it!
//
}

موفق باشید.

________________________________________
[1]: یک تکه کد (Code Snippet) آماده، کدی است که با تایپ یک کلمه خاص و سپس فشردن دکمه Tab در کد شما ایجاد میشه. (گفتنی است که میتوانید برای خودتان Snippetهای دلخواهتان را بسازید و سریع تر کد نویسی کنید!) مثلاً اگر کلمه mbox را تایپ کنید و پس از آن دکمه Tab را فشار دهید، تکه کد زیر ایجاد میگردد:

MessageBox.Show("Test");
در این پست، به اسنیپت invoke نیازمندیم، این Snippet، کد زیر را ایجاد میکنه:

EventHandler temp = MyEvent;
if (temp != null)
{
temp();
}

mohammad272005
پنج شنبه 10 فروردین 1391, 06:27 صبح
با تشکر از دوستان.
با اجازه اساتید، من سعی میکنم یکم ساده تر ولی بسیطتر موضوع رو بگم.
فرض کنید کلاسی دارید به نام Person که حاوی یه Property هست به نام Name از نوع String: public class Person
{
private string _Name;
public string Name
{
get { return this._Name; }
set { this._Name = value; }
}
}

حالا میخوایم کاری کنیم که به محض تغییر این Property، کاربر باخبر بشه.
برای این منظور نیار به یه event داریم. event هم فقط با delegate تعریف میشه.
برای این منظور یه delegeteِ ساده، تعریف میکنیم:public delegate void NameChangedDel();
حالا نوبت تعریف خود eventِ:
public delegate void NameChangedDel();
public class Person
{
public event NameChangedDel NameChanged;
private string _Name;
public string Name
{
get { return this._Name; }
set { this._Name = value; }
}
}

خب حالا که event رو تعریف کردیم. یه جا هم باید raise بشه. از اونجایی که قرارِ این event، تغییرات Name رو خبر بده، بهترین جا برای raise کردن event، خود propertyِ:
public delegate void NameChangedDel();
public class Person
{
public event NameChangedDel NameChanged;
private string _Name;
public string Name
{
get { return this._Name; }
set
{
this._Name = value;
NameChanged();
}
}
}
ملزومات اصلی تموم شد.
ولی وقتی از این کد استفاده میکنیم، در اولین استفاده، ممکنه ایجاد اشکال کنه. چون ممکنه NameChanged خالی باشه. یعنی، کاربر کلاس، handlerی برای event، ایجاد نکرده باشه. پس این شرط رو هم حتما باید الحاظ کنیم:
public delegate void NameChangedDel();
public class Person
{
private string _Name;
public string Name
{
get { return this._Name; }
set
{
this._Name = value;
if (this.NameChanged != null)
this.NameChanged();
}
}
public event NameChangedDel NameChanged;
}
حالا نحوه ی ایجاد Handeler:
در کلاسی که میخواد از Person استفاده کنه، اینطوری مینویسیم:
internal class Program
{
private static void Main(string[] args)
{
var ali = new Person();
ali.NameChanged += ali_NameChanged;
}
private static void ali_NameChanged()
{
Console.WriteLine("ali is changed.");
}
}
حالا فرض کنید، چندتا Instance داشته باشیم و همه eventها رو بخوایم هدایت کنیم به یه handler تکلیف چیه؟
باید delegate رو به نحوه تغییر بدیم که حاوی خود instance هم باشه:
public delegate void NameChangedDel(object sender);
تا اینجا کدمون به این ترتیب شده:
internal class Program
{
private static void Main(string[] args)
{
var ali = new Person();
ali.NameChanged += ali_NameChanged;
}
private static void ali_NameChanged(object sender)
{
Console.WriteLine("ali is changed.");
}
}
public delegate void NameChangedDel(object sender);
public class Person
{
private string _Name;
public string Name
{
get { return this._Name; }
set
{
this._Name = value;
if (this.NameChanged != null)
this.NameChanged(this);
}
}
public event NameChangedDel NameChanged;
}
حالا اگه بخوایم مقدار قبلی و جدید رو به کاربر بگیم، باید چیکار کنیم؟ در اینجا، event، نیازمند آرگومان میشه. برای این منظور، باید کلاس آرگومان رو به نحو زیر، ایجاد کنیم:
public class NameChangedEventArgs
{
public string OldName { get; set; }
public string NewName { get; set; }
}
و در delegate استفاده کنیم:
public delegate void NameChangedDel(object sender, NameChangedEventArgs e);
پس کل سورس باز باید عوض بشه:
internal class Program
{
private static void Main(string[] args)
{
var ali = new Person();
ali.NameChanged += ali_NameChanged;
}
private static void ali_NameChanged(object sender, NameChangedEventArgs e)
{
Console.WriteLine("{0} is changed to {1}.", e.OldName, e.NewName);
}
}
public delegate void NameChangedDel(object sender, NameChangedEventArgs e);
public class Person
{
private string _Name;
public string Name
{
get { return this._Name; }
set
{
var oldName = this._Name;
this._Name = value;
if (this.NameChanged != null)
this.NameChanged(this, new NameChangedEventArgs {OldName = oldName, NewName = this._Name});
}
}
public event NameChangedDel NameChanged;
}
public class NameChangedEventArgs
{
public string OldName { get; set; }
public string NewName { get; set; }
}
کار تمومه. ولی NET. راه حلهای آسونتری هم گذاشته. مثلا، همینطور که میبینید، event ما شبیه eventهای NET. شد. NET. یه delegate داخلی واسه اینکار تعبیه کرده و ما رو از تعریف delegate بی نیاز کرده.
namespace System
{
[ComVisible(true)]
[Serializable]
public delegate void EventHandler(object sender, EventArgs e);
}
خوبه. ما هم از همین استفاده میکنیم و delegate خودمون رو حذف میکنیم. ولی یه مشکل هست. تکلیف آرگومانمون چی میشه؟ NET. این مشکل رو هم با یه delegateِ جنریک حل کرده:
public delegate void EventHandler<TEventArgs>(object sender, TEventArgs e);
فقط این delegate ما رو ملزم به ارث بری از کلاس EventArgs خود NET. میکنه. باشه. ما هم پیروی می کنیم:
internal class Program
{
private static void Main(string[] args)
{
var ali = new Person();
ali.NameChanged += ali_NameChanged;
}
private static void ali_NameChanged(object sender, NameChangedEventArgs e)
{
Console.WriteLine("{0} is changed to {1}.", e.OldName, e.NewName);
}
}
public class Person
{
private string _Name;
public string Name
{
get { return this._Name; }
set
{
var oldName = this._Name;
this._Name = value;
if (this.NameChanged != null)
this.NameChanged(this, new NameChangedEventArgs {OldName = oldName, NewName = this._Name});
}
}
public event EventHandler<NameChangedEventArgs> NameChanged;
}
public class NameChangedEventArgs : EventArgs
{
public string OldName { get; set; }
public string NewName { get; set; }
}

cs_mz88
جمعه 11 فروردین 1391, 15:30 عصر
ممنونم استاد عزیز
فقط یک سوال.
همیشه event بوسیله deleget باید بنویسیم؟؟
دونستن همینقدر درباره delegetها کافیه؟
اگه مقاله یا فایل آموزشی دارید نه شما از همه اساتیدی که در این تاپیک بهم کمک کردن خواهش میکنم از deleget ها و event ها بزارید.
یک دنیا ممنون

mohammad272005
جمعه 11 فروردین 1391, 17:33 عصر
همیشه event بوسیله deleget باید بنویسیم؟؟
بله، event بدون delegate امکان نداره. البته در سطح NET. . جاهای دیگه رو اطلاع دقیق ندارم.

دونستن همینقدر درباره delegetها کافیه؟
در مورد delegateها، هرچی بیشتر بدونید، بهتره. شدیدا کاربردی هستن. در مورد event، همینقدر لازمه و در ساده ترین حالت، کافی. ولی اگه Action، Func و جنریک رو یاد بگیرید، eventهای بهتری میتونید بنویسید. در ضمن، مایکروسافت برای نوشتن eventها، واسه خودش یه Design Pattern داره که بد نیست اون رو هم یاد بگیرید.

cs_mz88
جمعه 11 فروردین 1391, 17:38 عصر
برای یاد گرفتن اون مبحث هایی که شما فرمودید میشه کتابی رو معرفی کنید

mohammad272005
جمعه 11 فروردین 1391, 18:05 عصر
مرجع اصلی من برای دانلود کتاب اینجاست (http://www.persiadevelopers.com/Books/) و برای فیلم اینجا (http://channel9.msdn.com/)

cs_mz88
دوشنبه 14 فروردین 1391, 21:24 عصر
دوستان میشه درباره event handler ها آموزشی بدید؟