PDA

View Full Version : سوال همیشگی فراخونی فرمی در فرم دیگر و یک راه حل



Sajjad1364
چهارشنبه 06 خرداد 1388, 23:49 عصر
مدتها بود که هر از چندگاهی اعضای تالار سوالاتی مبنی براینکه : چطو میشود فرمی را در داخل فرم دیگر صدا زد را مطرح می کردند
استفاده از متغیرهای سراسری و روش هایی که به استفاده مکرر و گیج کننده از نام فرم ها در فرم های دیگر منجر میشود و نمونه سازی های مکرر از فرم ها باعث میشود به فکر راه حل خوب و انعطاف پذیری بیافتیم.
بدون تعریف متغیرهای سراسری و با استفاده از Extension Method ها میتوان این کار را انجام داد.
خوب سراغ راه حل می رویم :

برای تعریف Extension Method باید کلاس ایستایی (static) تعریف کنیم :


public static class FormExtension
{

}


نکته : میتوانید این کلاس را در فایلی جداگانه در پروژه جاریتان و یا آنرا در یک پروژه جداگانه از نوعClass Library تعریف کنید
و در هر پروژه ای که خواستید آنرا به صورت رفرنس به پروژه خود اضافه کنید.

متد <ShowThisForm<T فرمی را که مد نظر شماست نمایش میدهد . در صورتیکه فرم مورد نظر شما قبلا در حافظه باشد آنرا نمایش میدهد و Focus را در اختیارش میگذارد اما اگر در حافظه نباشد آنرا ایجاد و بعنوان فرم جاری آنرا نمایش میدهد ( Show میشود نه ShowDialog).
بدنه این متد به صورت زیر تعریف میشود.


public static void ShowThisForm<T>(this FormCollection allForm) where T : Form, new()
{
T t = new T();
String _Type = t.GetType().Name;
Form form = allForm.Cast<Form>()
.FirstOrDefault(f => f.GetType().Name == _Type);
if (form != null)
{
if (!form.Focused)
{
form.Show();
form.Focus();
}
}
else
{
t.Show;()
{
{



حالا اگر مثلا در Form1 بنویسیم :


;()<Application.OpenForms.ThisForm<Form3


Form3 نمایش داده میشود.
شما میتوانید بجای Form3 بنویسید مثلا Form2 ,.....

متد بعدی ، باز هم یک Extension Method میباشد که فرمی را که مد نظر شماست را برمیگرداند.
اگر این فرم در حال حاضر در حافظه موجود باشد (یعنی فقط یکبار Show شده باشد ورها شده است) آنرا یرمی گرداند .اما اگر در حافظه نبود مقدار null بازگردانده میشود. مزیت استفاده از این متد اینست که این متد یک فرم تعیین نوع شده (Typed Form) را در اختیار شما قرار میدهد که احتیاج ندارید صریحا تبدیل نوع انجام بدهید.
به عنوان مثال اگر در Form4 متدی بنام MinimizeForm دارید برای فراخوانی آن کافیست بنویسید :


;()Application.OpenForms.ThisForm<Form4>().MinimizeForm


با استفاده از Extension Method ها میتوان کدهای کارآمدی را تولید کرد و تمام مزیت این دو متد جدای از راحت شدن کار اینست که ما هیچ نوع تازه ای ایجاد نکردیم که از کلاس FormCollection ارث بری داشته باشد واین متدها خود به خود به این کلاس اضافه میشوند.
حالا تمام کدی که باید در کلاس نوشت به اینصورت است.


public static class FormExtension

}
public static T ThisForm<T>(this FormCollection allForm) where T : Form, new()
{
T t=new T();
String _Type = t.GetType().Name;
Form form = allForm.Cast<Form>()
.FirstOrDefault(f => f.GetType().Name == _Type);
if ( form!= null)
{
return (T)form;
}
else
{
return default(T);
}
}

public static void ShowThisForm<T>(this FormCollection allForm) where T : Form, new()
{
T t = new T();
String _Type = t.GetType().Name;
Form form = allForm.Cast<Form>()
.FirstOrDefault(f => f.GetType().Name == _Type);
if (form != null)
{
if (!form.Focused)
{
form.Show();
form.Focus();
}
}
else
}

;()t.Show

{
{
{


پرانتزها و یا آکولادها ممکن هست جابجا بشوند.:چشمک:
موفق باشید

linux
پنج شنبه 07 خرداد 1388, 00:39 صبح
من تا حالا چند پروژه که مجموعا بیش از 100 هزار خط کد هست شرکت داشتم راستش تاحالا اصلا لازم نشده اینجوری بین فرم ها دیتا بفرستیم ، نمی دونم این دوستان اصلا برای چی احتیاج به این کارا دارند!

Sajjad1364
پنج شنبه 07 خرداد 1388, 11:11 صبح
میشه بگین کجای این کلاس دیتا ردو بدل میشه و اصلا استفاده منطقی از Application.OpenForms و یا هر چیز دیگه ای رو چطور به ردوبدل کرن دیتا ربط میدین

NewFoxStudent
پنج شنبه 07 خرداد 1388, 12:36 عصر
نکات جالبی رو گفتین
ممنونم
اما یه سوال
حالا اگه فرمهایی که میخواهیم از این طریق اجرا کنیم نیاز به پارامتر داشتند باید چه کرد

Sajjad1364
شنبه 09 خرداد 1388, 01:25 صبح
اگه توجه کرده باشید از ژنریک ها در این بین استفاده میشود و انها هم در این رابطه امکاناتی در اختیار توسعه دهنده ها قرار نمیدهند.مثلا اگر میشد بجای ()new در امضای متد ShowThisForm بنوسیم (new(params object[] args خیلی خوب بود و میشد سوال شما را پوشش داد ، اما بحث فرستادن آرگومان به این متد خارج از وظایف تعریف شده برای وضعیت فعلی ژنریک هاست و نمیتوان از این متد برای چنین مصرفی استفاده کرد.
نتیجتا باید از Interface ها کمک گرفت به این صورت که Interface ی به نام IParameterizedForm که متدی بنام SetParameters دارد و پیاده سازی این Interface بصورت زیر است :

public interface IParametrs
{
void SetParameters(params object[] args);
{






در مرحله بعد امضای متد ShowThisForm به این شکل در می آید(یا اینکه میتوانید سربارگذاری کنید) :


: ( ShowThisForm<T>(this FormCollection allForm , params object[] args


where T : Form,IParameterizedForm , new()

این متد میتواند در نسخه قبلی خود هم باقی بماند و این نسخه را هم اضافه کنیم . یعنی هر وقت احتیاج داشتیم که دادهای را به سازنده فرم بفرستیم از این نسخه و در صورتیکه نیاز نبود از نسخه بدون پارامتر استفاده میکنیم.
تنها تفاوتی که این نسخه با نسخه بدون پارامتر دارد اینست که قبل از t.Show(); در بلاک elseمتدی که مربوط به Interface است را فراخوانی میکنیم تا متد پیاده سازی شده از سوی پارامتر T (که نوعی از فرم است) فراخوانی شود :

t.SetParameters(args);


فراخوانی این متد هم بدون در نظر گرفتن تعداد و نوع پارامترها به شکل زیر انجام میشود :


;( " ",Application.OpenForms.ShowThisForm<Form3>(10, 20


طبیعتا اگر Form3 بخواهد از این داده ها استفاده کند باید این Interface را پیاده سازی کند و متد پیاده سازی شده از سوی Form3 موظف است خود تمامی اعمال تبدیل نوع را انجام دهد.
مثلا متد پیاده سازی شده در این مثال باید بداند که اولین و دومین آرگومان را به نوع داده int تبدیل کند و سومی را هم به رشته.
کماکان میتوانید از نسخه بدون آرگومان ShowThisForm هم استفاده کنید
موفق باشید

NewFoxStudent
شنبه 09 خرداد 1388, 09:42 صبح
ممکنه منبع این اطلاعات رو معرفی کنید

Sajjad1364
یک شنبه 10 خرداد 1388, 00:54 صبح
ممکنه منبع این اطلاعات رو معرفی کنید
ببخشید اصلا متوجه منظورتون نمیشم. بنظر شما این توضیحات و کدها منبعی خارجی دارن :قهقهه:
بنظر من نوشتن چند سطر توضیحات و کد برای راحتی برنامه نویس های محترم تالار اینقدر تحقیق و تفحس برای نسبت دادن یه منبع به مسائلی جزئی کم لطفیه. امیدوارم من اشتباه متوجه شده باشم.

موفق باشید

Sajjad1364
یک شنبه 10 خرداد 1388, 02:11 صبح
باسلام
من این کلاس را برای استفاده در دیگر پروژه ها بصورت Class Library ایجاد کرده ام
نکته ای که باید به آن توجه داشت اینست که اگر فرمی در زمان بارگذاری بخواهد داده ای را دریافت کند باید Interface ی که ، IParameterizedForm نامیده شده و در فضای نام MyExtensionMethods وجود دارد را پیاده سازی کند اما اگر نیازی به انتقال هیچگونه داده ای نیست لزومی ندارد که این پیاده سازی انجام شود.

برای استفاده از این کلاس آن را در قسمت References اضافه کنید و دستور :

using MyExtensionMethods;

را هم اضافه کنید.
موفق باشید

NewFoxStudent
یک شنبه 10 خرداد 1388, 09:53 صبح
ببخشید اصلا متوجه منظورتون نمیشم. بنظر شما این توضیحات و کدها منبعی خارجی دارن :قهقهه:
بنظر من نوشتن چند سطر توضیحات و کد برای راحتی برنامه نویس های محترم تالار اینقدر تحقیق و تفحس برای نسبت دادن یه منبع به مسائلی جزئی کم لطفیه. امیدوارم من اشتباه متوجه شده باشم.
منظورم اینایی که شما فکر کردید نبود
منظورم فقط این بود که ببینم شما اینا رو از جایی خوندی یا خودت بلد بودی (از وقتی که متولد شدی)
یا مثلا از Help VS خوندی
ولی اینجوری که شما صحبت میکنی فکر کنم از له توحظلد اینارو میدونستی :تشویق:

Sajjad1364
یک شنبه 10 خرداد 1388, 11:02 صبح
بنظر شما اگر کسی چیز پیش پا افتاده ای رو بذاره اینجا ، یا از جایی دیده ، یا از MSDN مطالعه کرده و یا از لحظه تولد بلد بوده. در اینصورت تمامی مطالب ومقالات مفید که در این تالار هست از سه حالت تعریف شده شما خارج نیست و این وسط خلاقیت و علاقه و بنیه علمی و..... همه پشم:قهقهه:

NewFoxStudent
یک شنبه 10 خرداد 1388, 12:21 عصر
این که شما ذهن خلاقتون بیشتر از این سه تا رو نمیبینه دلیل نمیشه که این مسئله رو به مقالات تالار بسط بدی
در ضمن من فقط میخواستم بدونم منبع شما در یادگیری این مسئله پیش پا افتاده چی بوده تا راجع به اون بیشتر تحقیق کنم همین. حالا شما میگی این مطالب پیش پا افتاده رو بوسیله بنیه علمی یا همون پشمتون یادگرفتین یا از تجربیات دیگران استفاده کردین یا از لحظه تولد بلد بودین یا توی کلاسهای دانشگاهتون اتفاقی شنیدین یا جبرائیل اومده بهتون وحی کرده یا خوابشو دیدین یا کتابی خوندین یا تو همین سایت دیدین یا اصلا این یه ابدای جدید از خودتون یا ........... و یا اینکه اصلا نمیخوای بگی به خودتون مربوطه

vcldeveloper
یک شنبه 10 خرداد 1388, 13:23 عصر
در ضمن من فقط میخواستم بدونم منبع شما در یادگیری این مسئله پیش پا افتاده چی بوده تا راجع به اون بیشتر تحقیق کنم همین.
این را می تونید با لحن مناسب تری هم از کاربران بپرسید. نیازی نیست از طبع لطیفتان برای اینگونه سوالات مایه بگذارید، و بحث تولد و جبرائیل و پشم(!) و غیره را پیش بکشید!

سعی کنید با دیگران، در هر سطحی که هستند، محترمانه برخورد کنید تا دیگران هم با شما محترمانه برخورد کنند.