الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

كيف أتعامل مع الاحداث؟

مغلق
بدأه Mr.Abdulilah في 13 فبراير 2006 · 5 رد · 1,323 مشاهدة · في Microsoft Visual C#.NET
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

بسم الله الرحمن الرحيم

========================================================================

لقد واجهتني مشكلة في الاحداث :-

كيف أتعامل مع الاحداث؟ :blink: ولو بضرب مثال بسيط :)

========================================================================

#2

السلام عليكم

الحدث هو اي شئ يفعلة المستخدم فى البرنامج

مثال

عند تقوم بالصغط علي زر موصوع علي الفورم هذا حدث ولكن قد يكون شئ ما يحدث عند الوقوف علي الزر فهذا ايضا حدث لان لكل اداة مجموعة من الاحداث ومعظم الادوات لها نفس الاحداث

مثال عملي بسيط للتوضيح :

انشاء فورم وضع عليها زر و صندوق نصي

قف علي الزر ثم اذهب الي الخصائص ثم اضغط علي زر الاحداث ليظهر لك احداث الزر

نختار الحدث Click اضغط علية مرتين متتاليتن يفتح لك الكود الخاص بالزر بالحدث ويكون بهذا الشكل

private void button1_Click(object sender, System.EventArgs e)
{
  
}

اعلم ان ما نكتبة الان يتفعل عند الضغط علي الزر

نريد ان نظهر رسالة فى الصندوق النصي اكتب التالي

private void button1_Click(object sender, System.EventArgs e)
{
textBox1.Text = "The Events Click";  
}

وهذا المثال ينطبق مع باقي الاحداث

مثال اخر نجرب عند الكتابة داخل الصندوق النصي يتغير لون الفورم حسب اللون المختار نفرض الابيض اكتب التالي ولحظ الحدث المختار

private void textBox1_TextChanged(object sender, System.EventArgs e)
{
	BackColor = System.Drawing.Color.White;
}

وكنت اود وضع المثال و الرد وبه الصور ولكن يبدو ان هناك شئ غير صحيح بالمنتدي

لا تنسونا من صالح دعائكم والسلام عليكم

#3

شكرا يا أخ "التابعي" ومن الواضح أنه يوجد شئ غير مظبوط بالمنتدى ! عموما التعامل مع الأحداث يا أخ "الممتاز" هو أمر بسيط وذلك لأن التعامل مع جميع الأحداث ( خصوصا الموجوده في الـ WindowsForms ) يكاد أن يتشابه وبالتالي يصبح التعامل مع تلك الأحداث شيئا روتينيا. بالاضافه أيضا الى ما تقدمه الـ Visual Studio من تسهيلات رائعه في هذا الأمر.

عموما , أول شئ لكى نخبر البرنامج أننا نريد تنفيذ كود معين عندما يتم تنفيذ حدث ما , فالبديهي أن نقوم بكتابة هذا الكود أولا في دالة ما وبعد ذلك نخبر البرنامج بأن الكود الذي نود تنفيذه موجود في داله اسمها كذا.

مثلا اذا أردنا أن ننفذ كود لاظهار MessageBox اذا ضغط أحدهم على Button اسمه yourButton. فاننا أولا نكتب Method موجود بداخلها كود اظهار الـ MessageBox .. هكذا مثلا ::

public void YourButtonClicked()
{
MessageBox.Show("Our Message");
}

طبعا هذه داله عاديه كتبنا فيها الكود الذي نريده أن يتنفذ , بقى علينا الآن أن نخبر الـ Button الذي اسمه yourButton ان عندما يضغط أحدا عليك تقم فورا بتشغيل الداله أو الوظيفه التي كتبناها والتي اسمها YourButtonClicked.

في السي شارب لا يوجد طريقه صريحه تمكننا من ارسال اسم الداله التي نود تنفيذها هكذا الى الحدث مباشرة ولكن تستخدم طريقه خاصه , وهى استخدام الـ Delegates. والـ Delegate هو عباره عن مؤشر يشير الى Method واحده أو أكثر ويصف أشكال هذه الـ Methods التي يشير اليها ولا يستطيع أن يشير الى Methods لها أشكال أخرى غير تلك التي يصفها. وعندما يتم استدعاؤه فيتم استدعاء كل الدوال التي يشير اليها.

أى أنه ينبغي علينا عمل Delegate أولا , ثم نجعل هذا الـ Delegate يشير الى الداله أو الدوال التي نريدها أن تتنفذ عند حدوث حدث معين , وبعد ذلك نخبر الـ Button بهذا الـ Delegate. وبالتالي عندما يتفجر الحدث سيتم استدعاء الـ Delegate الذي بدوره سيستدعي الداله أو الدوال التي يشير اليها.

طبعا يوجد أكثر من نوع من الـ Delegates وليس كل الأحداث تستخدم نوع واحد فقط منهم , وحدث Click الذي في مثالنا هذا يستخدم Delegate اسمه EventHandler. وكما ذكرت لك أن الـ Delegate يقوم بوصف شكل الدوال التي يشير اليها , فلا نستطيع أن نجبره على الاشاره لدوال لها أشكال مختلفه عن التي يصفها.

الـ EventHandler هذا يصف شكل الدوال التي يشير اليها بأنها يجب أن ترجع void ( أى لا ترجع شئ ) وأيضا أن يكون بها 2 Parameters فقط وأول واحد منهما يكون من نوع Object والثاني يكون من نوع EventArgs.

أى أن الداله التي كتبتها في الأعلى لا تصلح , لأن الـ EventHandler يقول بأنه لن يشير الى دوال الا ويكون شكلها كذلك :

void YourButtonClicked2(object sender,EventArgs e)
{
// كود
}

طبعا الـ e و الـ sender و YourButtonClicked2 هى أسماء يمكن تغييرها ولكن المهم هنا هو أننا يجب أن نكتب الداله بنفس الشكل الذي يحبه الـ EventHandler حتى يمكن عمل Compile للبرنامج ! فهذا أمر اجباري.

الآن , كيف نقوم بانشاء Delegate من نوع EventHandler ونجعله يشير الى الداله ؟

الأمر هذا أيضا بسيط , فيمكننا انشاؤه بالطريقه المعتاده لانشاء أى شئ, مع تمرير اليه اسم الداله التي نريده أن يشير اليها :

EventHandler eHandler = new EventHandler(yourButtonClicked2);

لاحظ أن YourButtonClicked2 هى اسم الداله التي نريده أن يشير اليها ولذلك فشكلها يجب أن يكون من النوع الذي يصفه هذا الـ Delegate الذي ذكرته في الأعلى.

بعد ذلك لم يبقى لدينا أى شئ الآن الا اخبار الـ Button ( أفترض أنك سميته yourButton ) بأنه " اذا حدث حدث الـ Click لديك , قم باستدعاء هذا الـ Delegate ( الذي سميناه eHandler في الكود السابق ) ومالكش دعوه بالباقي احنا قايلين للـ Delegate ده على الدوال اللي المفروض ينفذها لما انت تنادي عليه " ولكى نخبره بذلك برمجيا وليس مصريا يمكننا أن نكتب ذلك :

yourButton.Click += eHandler;

هكذا ببساطه عندما يضغط أحدا على yourButton فسيتم استعاء الـ eHandler الذي بدوره سيتم استدعاء كل الدوال التي يشير اليها بالترتيب وفي هذا المثال نحن لم نجعله يشير الا الى داله واحده ( YourButtonClicked2 ). ولكى نجعل الـ eHandler يشير الى أكثر من داله يمكننا استخدام معامل الـ += بطريقه عاديه ::

eHandler += new EventHandler(YourMethod1);
eHandler += new EventHandler(YourSecondMethod);
... الخ ....

ولكن أهم شئ يجب أن تكون الدوال بالشكل الذي يصفه هذا الـ Delegate المسمى EventHandler وبالطبع يوجد أنواع Delegates أخرى تصف أشكال مختلفه للدوال. ولا تنسى أن تخبر الـ Button بهذا الـ Delegate حتى يتم تنفيذه , وعلى كل حال يمكنك أن تقوم بانشاء الـ Delegate وتجعله يشير الى داله معينه وتخبر الـ Button بهذا وتقتلها وتقفل الباب بكعب رجلك وتفتح الخزنه وتاخد الفلوس ... كله في حركه واحده ,, هكذا ::

yourButton.Click += new EventHandler(YourMethodName);
yourButton.Click += new EventHandler(YourSecondMethod);
... الخ ...

والكود السابق هو ما تستخدمه الـ Visual Studio وأيضا تدعمه , فحاول كتابة الكود الكود السابق مثلا ( يجب أن يكون لديك Button اسمه yourButton أولا ) وستجد عند كتابتك لعلامة ( = ) أن الفيجوال ستوديو أخبرتك أنه يمكنك أن تضغط على زر TAB مرة واحده لانشاء الـ Delegate بل وأيضا تمرر اسم افتراضي للداله التي يشير اليها الـ Delegate ( التي يجب أن تكتبها فيما بعد بالشكل الذي يصفه هذا الـ Delegate ) واذا ضغطت مره أخرى ستجدها أنشأت اليك داله في الكود لها الشكل الذي يصفه هذا الـ Delegate ,, أى ستجد أنك لم تكتب الا أشياء بسيطه اذا ضغطت على زر TAB مرتين بعد كتابة علامة الـ ( = ) ولن تجد داعي لتذكر أشكال الدوال التي يصفها كل Delegate فالـ Visual Studio ستذكرك دائما بذلك , بل وستكتب لك الداله الصحيحه ولن يتبقى اليك شئ الا كتابة ما تريد تنفيذه عندما يتم استعدائها.

اذا كنت تقوم بعمل Windows Application فاكتب الكود السابق في مكان مناسب , مثلا وهو الشائع في الـ Constructor الخاص بالـ Form بعد دالة الـ InitializeComponent , واذا كنت لا تريد أن تكتب شيئا أصلا , فيمكنك من خلال الـ Visual Studio كما ذكر الأخ "التابعي" أن تقوم بتحديد الشئ الذي تود أن تتعامل مع أحداثه ثم تضغط على F4 وبعد ذلك اضغط على علامة الـ Events التي تكون لونها أصفر وبعد ذلك اضغط ضغطه مزدوجه على الحدث الذي تريد أن تتعامل معه وستجد الـ Visual Studio قد كتبت لك كل شئ ونقلتك الى الداله التي سيتم استدعائها عندما يتنفذ الحدث لتكتب فيها ما تريد.

عموما مازال يوجد أشياء أخرى , ربما نتحدث عنها فيما بعد ان شاء الله.

تم تعديل هذه المشاركة بواسطة معتز شمس في 14 فبراير 2006 في 06:47

#Read

http://MoutazShams.blogspot.com

projects003.gif

أعتذر عن التغيب هذه الأيام نظرا للانشغال المريب

#4

شكرا لك أخي التابعي وأيضا الاخ معتز شمس ولكن :-

ما فائدة البارمترات الزائدة

(object sender,EventArgs e)

#5

للأسف المثال السابق ربما لن يوضح استخدام الـ EventArgs جيدا لأن الـ EventArgs هو الكلاس الأساسي ولا يوجد به خواص يمكن الاستفاده منها.

عموما كما ذكرت لك أن كل Delegate يحدد شكل الدوال والـ EventHandler الذي كان في المثال يحدد أنه يجب أن تكون الداله تستقبل Object و EventArgs. ومعظم الأنواع الأخرى من الـ Delegates الموجوده في الـ WindowsForms تحدد شكل الدوال بهذه الطريقه وهى أن أول برامتر يكون من نوع Object والثاني يكون EventArgs أو أى Type آخر يرث من EventArgs ويجب أن ترجع void. وهذا هو الشائع ولكنه ليس شرطا.

عندما يتفجر الحدث كما ذكرت لك فيتم استدعاء الـ Delegate الذي بدوره سيستدعي الدوال ( التي قمت أنت بكتابتها ) التي يشير اليها بالترتيب , وقد يهمك أنت وانت في داخل تلك الدوال أن تعرف بعض المعلومات المصاحبه للحدث وأيضا قد يهمك أن تعرف من الذي فجر هذا الحدث. مثلا اذا كنت تتعامل مع حدث الـ MouseMove فالـ Delegate الخاص به اسمه MouseEventHandler وهذا الـ Delegate يصف شكل الدوال بأنها يجب أن تستقبل أول براماتر من نوع Object والثاني من نوع MouseEventArgs أى يجب أن تكون الداله بهذا الشكل :

 void YourButtonMMoved(object sender, MouseEventArgs e)
{
// كود
}

كما ذكرت لك أنه قد يهمك معرفة بعض المعلومات المصاحبه للحدث وأنت دخل الداله , ويتم معرفة تلك المعلومات من خلال الـ e فهى تحمل بعض المعلومات الخاصه بالحدث وبما أن الحدث يتعلق بتحرك الماوس ( MouseMove ) فالـ e تعطيك بعض المعلومات الخاصه مثلا باحداثيات الماوس الـ X و Y في الوقت الذي تفجر فيه الحدث , وأيضا بعض المعلومات الأخرى التي قد نستفيد منها في أحداث أخرى مثل MouseDown و MouseUP و MouseWheel والخ لأن تلك الأحداث تستخدم نفس الـ Delegate الذي يسمى MouseEventHandler الذي يستخدم MouseEventArgs بدلا من الـ EventHandler الذي كنت أستخدمه في ردي السابق والذي لا يحتوي على أية معلومات تصاحب الحدث.

مثلا قد يهمك عندما يحرك المستخدم الماوس على Button معين أن تعرض له رساله تخبره بالـ X والـ Y الخاصتين بالماوس أو لمعرفة تلك المعلومات حتى تتخذ قرار معين :

 void YourButtonMMoved(object sender, MouseEventArgs e)
{
MessageBox.Show("X = " e.X + " Y = " + e.Y );

// ويمكنك اتخاذ قرارات معينه بناء على موقع الماوس مثلا 
if(e.Y > 50 && e.X ==40)
{
// كود
}
}

ولا تسنى أن تخبر الـ Button باسم هذه الداله حتى يتم تنفيذها :

yourButton.MouseMove += new MouseEventHandler(YourButtonMMoved);

وبالتالي لو حرك المستخدم الماوس على yourButton فيتم تنفيذ الداله. وهكذا لكل الدوال التي تتعامل مع الأحداث فمن خلال البرامتر الثاني ( الذي عادة يسمى e ) وعلى حسب نوعه ( اذا كان من نوع EventArgs مثلا أو MouseEventArgs أو KeyPressEventArgs أو الخ ) فيمكننا استخلاص ما يوفره لنا من معلومات يمكننا من خلالها اتخاذ اجراءات معينه.

بالنسبه لأول برامتر الذي يكون عادة من نوع object فهو عادة يمثل الشئ ( الـ Object ) الذي فجر هذا الحدث , مثلا في أمثلتنا هنا فانه يمثل Object الـ Button نفسه الذي فجر الحدث , أى أن الـ ( sender ) في أمثلتنا هنا هو نفسه الـ yourButton , وقد يهمك وأنت داخل الداله التي تتعامل مع حدث معين أن تعرف " من الذي فجر هذا الحدث ؟ " وذلك أيضا لتقوم ببعض الاجراءات.

مثلا نفترض أننا نريد تغيير لون الـ Button اذا ضغط أحدا عليه , فيمكننا ونحن داخل دالة التعامل مع الـ Click أن نقوم بعمل ذلك باستخدام البرامتر الأول :

// yourButton.Click += new EventHandler(YourButtonClicked);

void YourButtonClicked(object sender,EventArgs e)
{
Button myButton = (Button) sender;
myButton.BackColor = Color.Black;
}

السطر الاول من الكود قمت فيه بالاعلان عن Button وجعلته يشير للـ sender ( أى الذي فجر الحدث أى يشير الى yourButton ) وطبعا استخدمت الـ Cast لأن الـ sender من نوع object وكان ينبغي تحويله الى شئ من نوع Button حتى أستطيع أن استخدم خواص الـ Buttons مثل تغيير خاصية الـ BackColor.

ويمكنك بدلا من انشاء Button جديد كتابة سطر واحد مباشرة :

((Button)sender).BackColor = Color.Black;

طبعا بما أننا نعرف أنه مادامت اشتغلت الداله فانه بالطبع زرار الـ yourButton هو من فجر الحدث , فلماذا لم نكتب ذلك مباشرة :

yourButton.BackColor = Color.Black;

طبعا كان يمكننا أن نفعل ذلك بدون أن نفكر في استخدام الـ ( sender ) , ولكن تذكر أنه يمكننا ان نجعل هناك داله واحده تتعامل مع أكثر من حدث لأكثر من شئ مختلف , مثلا افترض أننا نريد أن نعرض MessageBox اذا ضغط المستخدم على yourButton أو myButton , فليس من المعقول أن نقوم بعمل دالتين متشابهتين تماما فهذه مضيعه للوقت , ولكن يمكننا استخدام نفس الداله هكذا :

yourButton.Click += new EventHandler(SomeButtonClicked);
myButton.Click += new EventHandler(SomeButtonClicked);

لاحظ أنني كتبت نفس اسم الداله أى أنه سيتم تنفيذ داله واحده للتعامل مع حدث الـ Click الخاص بـ myButton و yourButton. وهنا تضح أهمية البراماتر الأول الذي نتحدث عنه الذي يكون من نوع object , فافرض أننا في هذه الحاله نريد أن نعرف مثلا اسم الـ Button الذي ضغط عليه المستخدم لنعرضه له في الـ MessageBox أو للتعامل معه كتغيير لونه مثلا أو ماشابه , فكيف نعرف الـ Button اذا كنا نستخدم نفس الداله للتعامل مع أحداث الـ Click الخاصه بأكثر من Button ؟ نعرفه من خلال الـ sender ( البارامتر الأول ) ونقوم بعمل cast له ونتعامل معه كما نريد , مثلا :

void SomeButtonClicked(object sender, EventArgs e)
{
Button clickedButton = (Button)sender;
MessageBox.Show(clickedButton.Name);
clickedButton.BackColor = Color.Black;
}

في الكود السابق سيتم عرض اسم الـ Button الذي ضغط عليه المستخدم وسيتم تغيير لونه , وهنا أهمية البرامتر الأول فيمكنك أن تجعل الداله SomeButtonClicked تتعامل مع ألف حدث Click لألف Button مختلف وسيتم تنفيذها وستتعامل مع الـ Button الذي ضغط عليه المستخدم فقط , وذلك بدلا من كتابة ألف داله متشابهه لكل Button على حده تقوم بعمل نفس الوظيفه.

#Read

http://MoutazShams.blogspot.com

projects003.gif

أعتذر عن التغيب هذه الأيام نظرا للانشغال المريب

#6

شكرا جزيلا لك يأخ معتز شمس لقد تم الفهم

هذا الموضوع مغلق.

مواضيع مشابهة