PDA

View Full Version : حرفه ای: اطلاع از رخداد یک Event به پنجره بالا دستی (Parent)



Sal_64
پنج شنبه 04 مهر 1392, 17:48 عصر
سلام
اینطور فرض کنید که یک یوزرکنترل را به فرم(پنجره) اضافه کردیم ، و حالا داخل فرم نیاز داریم متوجه شویم که فلان رویداد آیا در یوزر کنترل به وقوع پیوسته است یا خیر که همزمان با آن کاری را در پنجره اصلی انجام دهیم

مثلا : در فرم میخواهیم متوجه شویم که آیا رویداد کلیک بر روی باتم در یوزرکنترل اتفاق افتاده یا خیر

با فرض اینکه نباید رویداد مربوط به یوزر کنترل را در داخل فرم اصلی تعریف کنیم

امیدوارم توضیحاتم کافی بوده باشه

تشکر

plus
پنج شنبه 04 مهر 1392, 18:39 عصر
راه هایی هست اما راه منطقی به نظر همون تعریف یک رویداد در UserControl و Raise کردن اون هنگام کلیک دکمه و استفاده از رویداد UserControl در فرم پدرهست:

public Form1 : Form
{
public Form1()
{
InitializeComponents();
userControl11.SomeButtonClicked += new EventHandler(userControl11_someButtonClicked); // Subscribe

}
private userControl11_someButtonClicked(object sender, EventArgs e)
{
MessageBox.Show("SomeButton on usercontrol is clicked!");
}
///
}

public UserControl1: UserControl
{
public event EventHandler SomeButtonClicked;

public UserControl1()
{
InitializeComponents();
this.SomeButton.Click += new EventHandler(someButton_Click);
}
private userControl11_someButtonClick(object sender, EventArgs e)
{
if (this.SomeButtonClicked != null)
this.SomeButtonClicked(this, EventArgs.Empty);
}
}

شما اگه نخواین از Event برای این کار استفاده کنین، میتونید به یه نحو دیگه الگوی Observer رو پیاده کنید ولی نتیجه شبیه همین خواهد بود.
البته اگه میخواین که فرم به صورت مستقیم نقش Observer رو ایفا نکنه راه های دیگه ای هم هست.مثلا:

public interface ISomeButtonClickReceiver
{
void SomeButtonClicked();
}
public Form1 : Form, ISomeButtonClickReceiver
{
public SomeButtonClicked()
{
MessageBox.Show("SomeButton is clicked!");
}
}
public UserControl1: UserControl
{
public UserControl1()
{
InitializeComponents();
this.SomeButton.Click += new EventHandler(someButton_Click);
}
private userControl11_someButtonClick(object sender, EventArgs e)
{
if (this.Parent is ISomeButtonClickReceiver)
((ISomeButtonClickReceiver)this.Parent).SomeButton Clicked();
}
}

Sal_64
پنج شنبه 04 مهر 1392, 19:17 عصر
سلام
تشکر
آیا این امکان وجود داره که از داخل یوزر کنترل ،پس از وقوع یک رخداد با دستور Parent.Invoke و یا دستور مشابه رویداد خاصی را در parent فراخوانی کرد ؟

plus
پنج شنبه 04 مهر 1392, 19:36 عصر
از اونجا که در حالت عادی رویداد UI مربوط به UserControl در همون Thread ی اجرا میشه که Parent اون اجرا میشه، استفاده از Invoke کار خاصی رو در این مورد انجام نمیده.ولی با استفاده از Reflection میشه کارهایی رو انجام داد. (اینجا (http://stackoverflow.com/questions/198543/how-do-i-raise-an-event-via-reflection-in-net-c)رو ببینید) و یا اینکه اگه رویداد مروبط به User Interface هست با استفاده از Windows API و ارسال Message مناسب رویداد مورد نظر رو Raise کرد.ولی هر دوی این راه ها کلا راه مناسب نیستن.چون صورت مساله غلط هست. راه حل عادی همون تعریف Event هست.شما اگه مساله ای که دارین رو کامل تر مطرح کنید شاید راه حل صحیح رو پیدا کنید..

Sal_64
پنج شنبه 04 مهر 1392, 19:46 عصر
ببینید در یوزرکنترل با کلیک روی باتم یکسری عملیات انجام میشه و حاصل اون به صورت datatable در میاد ، بلافاصله باید اون دیتاتیبل در فرم اصلی مورد استفاده قرار بگیره

plus
پنج شنبه 04 مهر 1392, 20:50 عصر
خوب همون سناریوی تعریف Event که اول گفتم برای این نیاز پاسخگو هست.برای ارائه DataTable به فرم، یک راه تعریف یک Property در UserControl هست:

public Form1 : Form
{
public Form1()
{
InitializeComponents();
userControl11.SomeButtonClicked += new EventHandler(userControl11_someButtonClicked); // Subscribe

}
private userControl11_someButtonClicked(object sender, EventArgs e)
{
DataTable data = userControl11.Data;
// Do whatever with data...
}
}

public UserControl1: UserControl
{
public event EventHandler SomeButtonClicked;
private DataTable data;

public UserControl1()
{
InitializeComponents();
this.SomeButton.Click += new EventHandler(someButton_Click);
}
private userControl11_someButtonClick(object sender, EventArgs e)
{
// Do caluclations
// ...
this.data = [Result Data Table];
if (this.SomeButtonClicked != null)
this.SomeButtonClicked(this, EventArgs.Empty);
}
public DataTable Data
{
get { return this.data; }
}
}

و یا اگه DataTable مورد نظر مسقیما با رویداد در ارتباط میتونید اون رو به عنوان آرگومان رویداد به فرم ارسال کنید:

// Define event args
public SomeButtonClickedEventArgs : EventArgs
{
private DataTable data;
public SomeButtonClickedEventArgs(DataTable data)
{
this.data = data;
}
public DataTable Data
{
get { return this.data;}
}
}

// Define event handler
public delegate void SomeButtonClickedEventHandler(object sender, SomeButtonClickedEventArgs e);

//
public Form1 : Form
{
public Form1()
{
InitializeComponents();
userControl11.SomeButtonClicked += new SomeButtonClickedEventHandler(userControl11_someBu ttonClicked); // Subscribe

}
private userControl11_someButtonClicked(object sender, SomeButtonClickedEventArgs e)
{
DataTable data = e.Data;
// Do whatever with data...
}
}

public UserControl1: UserControl
{
public event SomeButtonClickedEventHandler SomeButtonClicked;

public UserControl1()
{
InitializeComponents();
this.SomeButton.Click += new EventHandler(someButton_Click);
}
private userControl11_someButtonClick(object sender, SomeButtonClickedEventArgs e)
{
// Do caluclations
// ...
DataTable data = [Result Data Table];
SomeButtonClickedEventArgs ea = new SomeButtonClickedEventArgs(data);

if (this.SomeButtonClicked != null)
this.SomeButtonClicked(this, ea);
}

}

Sal_64
پنج شنبه 04 مهر 1392, 21:24 عصر
تشکر بابت وقتی که گذاشتی
اگه مثله کنترل های فرم والد به توابع هم میشد دسترسی مستقیم داشت ، در این کار حجم کد نویسی به شدت پایین می اومد

Sal_64
پنج شنبه 04 مهر 1392, 21:55 عصر
بنده روش دیگه ای اجرا کردم
ایونت کلیک باتم داخل یوزر کنترل کارها انجام میده و دیتاتیبل تولید میکنه
سپس مجدد همون ایونت داخل فرم هم تعریف کردم که با متد GET کارش فقط گرفتن دیتاتیبل ایجاد شده از یوزر کنترل
سرجمع 3 -4 خط کد نویسی اضافه

حالا سوالم از دوستان اینه که آیا این شیوه درسته