استفاده از کاستوم ایونت برای عملیات جستجو در سی شارپ

سلام توی این آموزش میخوام درمورد استفاده از Custom Events در سی شارپ صحبت کنم، اینکه چطور میتونیم داخل برنامه هامون با یه روش حرفه ای اطلاعات موردنظرمون رو به فرم های دنبال کننده پاس بدیممساله رو اینجوری در نظر بگیریم:فرض کنید یک فرم جستجو داریم که توش یک دیتاگرید هست میخوایم وقتی کاربر از فرم دیگه ای به این فرم مراجعه کنه و روی یکی از سطرها کلیک کنه، اطلاعات این سطر از دیتاگرید به فرم قبلی بازگشت داده بشه.حالا آیا راهی داره که کاربر از هر فرمی که وارد این فرم جستجو میشه، اطلاعات دیتاگرید به همون فرم برگرده؟برای اینکار یه روش خیلی مبتدیانه اینه که یه پراپرتی استاتیک در سطح برنامه تعریف کنیم که هروقت نیاز به اطلاعات بازگشتی از فرم جستجو بود، اطلاعات موردنیاز رو داخل این پراپرتی استاتیک قرار بدیم و داخل فرم موردنظر ازش استفاده کنیم و مابقی ماجرا (بنده اصلا این روش رو پیشنهاد نمیکنم، چون روش خیلی چیپیه)راه حرفه ایش استفاده از Custom Events هستش، یعنی شما یه ایونت مینویسین که هر موقع روی سطر موردنظر روی دیتاگریدویو کلیک شد، فرم جستجو بسته بشه و اطلاعات موردنیاز در قالب یک Custom EventArgs به فرم دنبال کننده (همون فرمی که میخواین اطلاعات بهش بازگشت داده بشه) پاس داده بشه به فرم یا کلاسی که ایونت رو داخلش تعریف میکنیم اصطلاحا میگیم Publisher یا انتشار دهنده و به فرم و یا کلاسی که میخوایم اطلاعات بازگشتی از ایونت رو دریافت کنیم اصطلاحا میگیم Subscriber یا دنبال کنندهبرای انجام اینکار توسط ایونت باید سه مرحله انجام بدیم:1. تعریف Delegate2. تعریف ایونت بر اساس اون دلیگیت3. فراخوانی ایونت خب برای مرحله اول لازمه که توی فرم جستجو (کلاس پابلیشر یا انتشاردهنده) داخل کلاس، یه delegate با signature زیر تعریف کنیم:public delegate void SearchEventHandler(object sender, EventArgs args);پس ایونتی که استفاده میکنیم باید از این signature تبعیت کنه، یعنی ریترن تایپش void باشه، دوتا پارامتر بگیره، اولی از جنس ابجکت و مشخص کننده کلاسیه که این ایونت رو ازش فراخونی میکنیم، دومین پارامتر از جنس کلاس EventArgs که شامل دیتا و اطلاعاتی میشه که لازم داریم (شما باید یه کلاس کاستوم برای eventargs بنویسین که اون اطلاعاتی که لازم دارین رو در خودش داشته باشه، در ادامه این رو هم توضیح میدم) حالا میایم داخل بدنه کلاس فرم جستجو یه نمونه ایونت از این دلیگیت میسازیم، بشکل زیر:public event SearchEventHandler ItemSelected;مرحله دوم هم تموم شد. حالا میرسیم به مرحله سوم، برای فراخوانی ایونت، باید یه متد تعریف کنیم که مسئول فراخوانی ایونت هستش، پس یه متد با signature زیر تعریف میکنیم:protected virtual void OnItemSelected(EventArgs args) { if(ItemSelected != null) { ItemSelected(this, args); } }توضیح متد بالا اینه که اگر اون ایونتی که تعریف کردیم دنبال کننده ای داشته باشه (یعنی توی کلاس یا فرم دیگه ای این ایونت رو فراخوانی کرده باشیم یا اصطلاحا ایونتمون فایر(fire) شده باشه) مخالف null میشه و داخل بدنه if اون رو دقیقا مثل یک متد معمولی فراخوانی میکنیم تا دنبال کننده ها رو از این ایونت باخبر کنیم، اما باید از اون signature که برای دلیگیت تعریف کردیم تبعیت کنه، پس پارامتر اول میشه کلاسی که ایونت رو فایر میکنه یعنی کلاس جاری (فرم جستجو)، پارامتر دوم هم شامل اطلاعات موردنیازمون هستش.به جای اون قطعه کد بالا، یعنی همون if و بدنه اون، میتونید از کد زیر استفاده کنید که خیلی خلاصه تره، ولی دقیقا همون کار قطعه کد بالارو انجام میدهItemSelected?.Invoke(this, args);اگر ایونتمون دنبال کننده ای نداشته باشه، ایونت برابر null خواهد بود. حالا متد OnItemSelected رو داخل رویداد دابل کلیک دیتاگرید ویو به این شکل فراخوانی میکنیم و اطلاعاتی که لازم داریم رو از طریق ابجکت args به متد OnItemSelected پاس میدیمOnItemSelected(new EventArgs { AccountNumber = Convert.ToString(dgv.SelectedRow.Cells[&quotAccountNumber&quot].Value), AccountOwner = // get the Account Owner });الان ما به فرم جستجومون (که ایونت رو داخل اون تعریف کردیم) publisher یا انتشاردهنده میگیم و میتونیم از این ایونت توی هر فرمی که لازم باشه به راحتی استفاده کنیم، نحوه استفاده از این ایونت به شکل زیره، فرضا توی فرم 1 هستیم و لازم داریم که فرم جستجو رو باز کنیم و از ایتمی که توی فرم جستجو انتخاب میشه استفاده کنیم:var searchingForm = new frmSearchingForm(); searchingForm.ItemSelected += frmSearchingForm_ItemSelected; private void frmSearchingForm_ItemSelected(object sender, EventArgs args) { // now your data is stored in args }توی کد بالا به ایونت هندلر frmSearchingForm_ItemSelected که توی فرم 1 داره ایونت ItemSelected توی فرم جستجو رو فراخوانی میکنه میگیم subscriber یا دنبال کننده اون ایونت (به تبع اون به کلاس فرم 1 هم دنبال کننده میگیم) کار تمومه. اما حالا درمورد اون کلاس custom eventargs که گفتم، باید یه کلاس تعریف کنید که از کلاس EventArgs ارث بری میکنه، و براش پراپرتی هایی که لازم دارین رو تعریف کنین:public class SearchEventArgs : EventArgs { public string AccountNumber {get; set;} public string AccountOwner {get; set;} }و برای استفاده از این کلاس باید توی کد های بالا، به جای تمامی EventArgs ها از کلاس SearchEventArgs استفاده کنید. نکته دیگه اینکه شما به جای تعریف یک دلیگیت میتونین از دلیگیت تعریف شده توی خود دات نت استفاده کنین، پس مرحله اول حذف میشه و فقط از مرحله دوم کار رو شروع میکنین، یکی از این دلیگیت های پیش فرض دلیگیت EventHandler هستش که باید از نوع جنریکش استفاده کنید و نوع SearchEventArgs رو بهش بدین، به این صورت:public event EventHandler<SearchEventArgs> ItemSelected;اگر از دلیگیت پیشفرض خود دات نت استفاده کنین، میتونین اون دلیگیتی که خودمون تعریف کردیم رو پاک کنین و مستقیما ایونت رو بسازیناین آموزش رو خیلی سال پیش توی این تاپیک داخل فوروم برنامه نویس نوشته بودم.