المساعد الشخصي الرقمي

مشاهدة النسخة كاملة : الدرس العاشر : التعامل مع أكثر من نافذة - دورة CSharp 2005


khaledbelal
03-22-2010, 04:02 PM
الدرس العاشر

المتغيرات العامة public
إلى الآن ما زال برنامجنا يحتوي على نافذة واحدة فقط , لذلك لم نجد الفرصة لإستخدام المتغرات العامة
في درس اليوم سنقوم بإضافة نافذة جديدة إلى البرنامج لإدارة الألبومات "قوائم التشغيل"
حيث سنحتاج للوصول إلى متغيرات النافذة الأساسية من نافذة الالبومات
المتغير الأساسي الذي سنحتاج للوصول إليه من نافذة الالبومات هو قائمة التشغيل albume
حيث يجب تمريرها إلى نافذة الألبومات حتى يتم إجراء التعديلات عليها
وهنا يجب إستخدام كلمة public قبل تعريف albume حتى تستطيع النافذة الأخرى التعرف عليها كما سنرى في التطبيق

التطبيق:
إفتح تطبيق الدرس السابق وإذهب إلى نافذة Project وأنقر بزر الفارة الأيمن على إسم البرنامج MyMediaPlayer
ومن القائمة إختر Add ثم New Item

http://absba7.absba.org/teamwork8/455943/78.jpg

ستظهر لك القائمة التالية :

http://absba7.absba.org/teamwork8/455943/79.jpg

إختر C# ثم Windows Application ثم Form وأكتب في حقل إسم الفورم albumes.cs
ثم انقر على زر Create لكي يتم إنشاء نافذة جديدة في المشروع
يتم التنقل عبر نوافذ البرنامج من خلال النقر المزدوج على ملف النافذة في نافذة Projects

http://absba7.absba.org/teamwork8/455943/80.jpg

أنتقل إلى تصميم النافذة الجديدة , ومن صندوق الأدوات قم بسحب كائن المستعرض List View إلى النافذة الجديدة

http://absba7.absba.org/teamwork8/455943/81.jpg

قم بإختيار كائن المستعرض وإذهب إلى جدول الخصائص
غير الخاصية (Name) إلى lv
وغير الخاصية View إلى Details
إذهب إلى خاصية Columns وأنقر على زر التفاصيل :

http://absba7.absba.org/teamwork8/455943/82.jpg

ستظهر نافذة التفاصيل فارغة
هذه هي النافذة التي يتم من خلالها إنشاء أعمده لكائن المستعرض

http://absba7.absba.org/teamwork8/455943/83.jpg

حيث سنكون عمودين , عمود لإسم الملف فقط , وعمود آخر لمسار الملف كاملاً
أنقر على زر Add وغير خاصية Text إلى "إسم الملف"
ونقر مرة أخرى على زر Add لتنشئ العمود الثاني وغير خاصية Text فيه إلى "مسار الملف"
ثم انقر على زر الموافقة سيتكون في كائن المستعرض عمودين :

http://absba7.absba.org/teamwork8/455943/84.jpg

من صندوق الأدوات إسحب أربعة أزرار إلى يمين كائن المستعرض , وغير خاصية Text إلى
إضافة
إلى الأعلى
إلى الأسفل
حذف
إسحب زرين آخرين من صندوق الأدوات إلى أسفل كائن المستعرض وغير خاصية Text إلى
موافق
إلغاء الأمر
بحيث يصبح شكل النافذة هكذا :

http://absba7.absba.org/teamwork8/455943/85.jpg

إختر زر "موافق" وإذهب إلى جدول الخصائص وغير الخاصية DialogResult إلى OK
معنى هذا أنه عند النقر على هذا الزر فإن نتيجة النا فذة هي الموافق كما سنشرح لاحقاً
ثم إختر زر "إلغاء الأمر" وغير خاصية DialogResult إلى Cancel
وهذا يعني أنه عند النقر على هذا الزر فإن نتيجة النافذة هي إلغاء الأمر
من صندوق الأدوات إسحب كائن فتح الملفات و إختره وغير خاصية (Name) إلى OF
وغير خاصية MultiSelect إلى true
إنتقل إلى شفرة النافذة , نحتاج لتعريف متغير من نوع قائمة شبيهه بقائمة albume في النافذة الرئيسية
حتى يتم من خلالها التعامل مع الملف وإضافتها إلى كائن المتصفح و حذفها منه
وكما شرحنا سابقاً فإن كائن القائمة موجود في فضاء الأسماء System.Collections.Generic لذلك يجب إضافة عبارة using لتضمين كائنات ودوال الفضاء
إذهب إلى شفرة النافذة وأضف عبارة using التالية تحت عبارات using الموجوده في رأس الصفحة :

using System.Collections.Generic;

ثم أكتب كود تعريف القائمة تحت تعريف كائن النافذة :

public List<string> albume=new List<string>();

http://absba7.absba.org/teamwork8/455943/86.jpg

لاحظ أنا إستخدمنا الكلمة public وليس private وذلك حتى تتمكن النافذة الرئيسية من رؤية هذا المتغير كما سنرى لاحقاً
القائمة albume في نافذة الألبومات ستكون نسخة مطابقة للقائمة albume في النافذة الرئيسية
ويتم التعامل مع كائن المستعرض من خلال عناصر هذه القائمة .

إضافة ملفات
إنتقل إلى تصميم نافذة الالبومات وأنقر مزدوجا على زر "إضافة" للذهاب إلى شفرته
أكتب الكود التالي بين الحاصرتين :

OF.ShowDialog();
albume.AddRange(OF.FileNames);
FillView();

يقوم هذا الكود بفتح نافذة إختيار الملفات ثم إضافة الملفات المختارة إلى القائمة albume
في السطر الثالث نستدعي إجراء إضافة الملفات إلى كائن المستعرض

الإجراء FillView
يقوم هذا الإجراء بنسخ جميع عناصر القائمة albume إلى كائن المستعرض lv
إنسخ الإجراء التالي إلى شفرة نافذة الالبومات وتأكد من أنه خارج إلى إجراء أخر :

void FillView()
{
lv.Items.Clear();
for (int i = 0; i < albume.Count; i++)
{
string filename=System.IO.Path.GetFileName(albume[i]);
ListViewItem file = new ListViewItem(filename);
file.SubItems.Add(albume[i]);
lv.Items.Add(file);
}
}

فس السطر الثالث قمنا قمنا بإستدعاء دالة تنظيف كائن المستعرض lv.Items.Clear
حيث تقوم هذه الدالة بتنظيف كائن المستعرض من أي عناصر موجوده مسبقاً حتى يتم إضافة العناصر الجديدة
في السطر الرابع دوارة for من الصفر وحتى عدد عناصر القائمة albume التي تحمل مسارات الملفات المختارة
في السطر السادس قمنا بتعريف متغير من نوع نص يحمل ناتج دالة GetFileName والتي ترجع إسم الملف من المسار الموجود في قائمة albume في الترتيب i
في السطر السابع عرفنا كائن جديد إسمه file من نوع ListViewItem
حيث ان كائن المستعرض lv هو عبارة عن مجموعة كائنات ListViewItem حيث يمثل كل كائن منها سطر واحد من سطور كائن المستعرض
ولأن ListViewItem كائن وليس متغير فقد إستخدمنا الجملة new ومررنا له إسم الملف الناتج من السطر السابق
حيث أصبح المتغير يحمل قيمة filename من السطر السابق
وفي السطر الثامن , أضفنا كائن فرعي للكائن file من خلال الدالة file.SubItems.Add
ومررنا لها العنصر الذي ترتيبه i من قائمة albume
الآن المتغير file أصبح يحمل قيمتين الأولى هي إسم الملف والثانية الفرعية هي مسارة المخزن في قائمة albume
في السطر التاسع أضفنا الكائن file إلى lv حيث يعتبر سطر واحد من سطور كائن المستعرض lv
وبعد تكرار هذه العملية لكافة عناصر القائمة albume يصبح الكائن lv محتوياً على جدول يوضح جميع أسماء ومسارات الملفات المختارة

حذف ملف
إذهب إلى تصميم نافذة الألبومات وأنقر مزدوجاً على زر "حذف" لتنتقل إلى شفرته
أكتب الكود التالي بين الحاصرتين :

albume.RemoveAt(lv.SelectedIndices[0]);
FillView();

الدالة RemoveAt تقوم بأخذ ترتيب العنصر كمدخل وتحذفة من القائمة
فمثلاً لو أردنا حذف العنصر الذي ترتيبة 4 سيكون الكود كالتالي :

albume.RemoveAt(4);

لاحظ أن العنصر الذي ترتيبه 4 هو العنصر الخامس
الدالة SelectedIndices من دوال الكائن lv تقوم بإرجاع مصفوفة تحتوي على ترتيبات الأسطر المختارة في الكائن
فمثلاً لو أخترنا السطر الثالث و الرابع من القائمة سترجع الداله مصفوفة تحتوي رقمي 2 و 3
لاحظ , أن السطر الثالثة ترتيبة 2 وليش 3 كما شرحنا مراراً.
لكنا نريد عند النقر على زر الحذف أن يقوم البرنامج بحذف سطر واحد, وهو أول سطر من السطور المختارة

lv.SelectedIndices[0]

وفي السطر الثاني نقوم بإستدعاء الإجراء FillView والذي يقوم بنسخ محتويات القائمة albume إلى الكائن lv
ماذا لو تم النقر على زر الحذف وليس هناك أسطر مختارة من قبل المستخدم ,
سيظهر خطأ عندها , ولحل هذا الخطأ يجب أولاً فحص عدد العناصر المختارة فإذا كان أكبر من صفر
فذلك يعني أن هناك ملفات مختارة و بالتالي ينفذ كود الحذف ,
عدل الكود السابق حتى يصبح هكذا :


if(lv.SelectedIndices.Count>0)
{
albume.RemoveAt(lv.SelectedIndices[0]);
FillView();
}

يتم فحص عدد العناصر المختارة من خلال الخاصية lv.SelectedIndices.Count

نقل ملف إلى الأعلى
وظيفة هذا الزر هو إعادة ترتيب الملفات بحيث ينقل الملف المختار في كائن المستعرض إلى أعلى خطوة واحدة
إذهب إلى تصميم نافذة الألبومات و أنقر مزدوجاً على زر "إلى الأعلى"
وأكتب الكود التالي بين الحاصرتين :

int sel = lv.SelectedIndices[0];
string tmp = albume[sel];
albume[sel] = albume[sel-1];
albume[sel - 1] = tmp;
FillView();
lv.Items[sel-1].Selected = true;

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

http://absba7.absba.org/teamwork8/455943/87.jpg

حيث إفترضنا أن القائمة albume تحتوي على ثلاثة عناصر تم إختيار العنصر الأوسط لنقله خطوة إلى الأعلى
ماذا لو إختار المستخدم أول عنصر سطر في المستعرض , كيف سيتم نقل أول عنصر في القائمة خطوة إلى أعلى
سيحدث خطأ إذا حاول المستخدم فعل ذلك ولتفادي هذا الخطأ يجب أن نفحص ترتيب السطر المختار sel فإذا كان يساوي صفر
فمعناه أن المستخدم إختار أول عنصر في القائمة , ولا يجب تنفيذ كود النقل , إما إذا كانت قيمته أكبر من الصفر فلا مانع من تنفيذ كود النقل
عدل الكود السابق ليصبح هكذا :

int sel = lv.SelectedIndices[0];
if(sel>0)
{
string tmp = albume[sel];
albume[sel] = albume[sel-1];
albume[sel - 1] = tmp;
FillView();
lv.Items[sel-1].Selected = true;
}

ماذا لو لم يختر المستخدم أي سطر وقام بالنقر على زر النقل .. سيحدث هنا أيضاً خطأ , ويجب معالجته كما فعلنا في زر الحذف
عدل الكود السابق ليصبح هكذا :

if(lv.SelectedIndices.Count>0)
{
int sel = lv.SelectedIndices[0];
if(sel>0)
{
string tmp = albume[sel];
albume[sel] = albume[sel-1];
albume[sel - 1] = tmp;
FillView();
lv.Items[sel-1].Selected = true;
}
}

نقل ملف إلى أسف
يشبه كود نقل الملف لأعلى بإختلاف بسيط جداً فبدل من sel-1 نضع sel+1
وعند المقارنه sel>0 نضع sel<lv.Items.Count لأن النقل في هذه الحالة سيكون للأسفل
ويجب أن نفحص ما إذا كان ترتيب السطر المختار أقل من عدد سطور الكائن :
إفتح تصميم نافذة الألبومات وأنقر مزدوجاً على زر "إلى الأسف" وأنسخ الكود التالي بين

if(lv.SelectedIndices.Count>0)
{
int sel = lv.SelectedIndices[0];
if(sel<lv.Items.Count-1)
{
string tmp = albume[sel];
albume[sel] = albume[sel+1];
albume[sel + 1] = tmp;
FillView();
lv.Items[sel+1].Selected = true;
}
}

بهذا نكون قد أنتهينا من نافذة الألبومات ...
أنتقل إلى النافذة الرئيسية و من صندوق الأدوات إسحب كائن الزر إلى النافذة الرئيسية وغير النص إلى "التحكم بالألبومات"
اضبط ترتيب الأدوات في النافذة حتى يصبح شكلها هكذا :

http://absba7.absba.org/teamwork8/455943/88.jpg

إظهار نافذة الألبومات
إذهب إلى تصميم النافذة الرئيسية وأنقر مزدوجاً على زر "التحكم بالألبومات" لتنتقل إلى شفرته وانسخ الكود التالي بين الحاصرتين

albumes frm = new albumes();
frm.albume = albume;
frm.ShowDialog();
albume = frm.albume;
FillList();

في السطر الأول عرفنا كائن إسمه frm من نوع albumes , لاحظ أن albumes هو إسم نافذة الألبومات
اي أنها الآن تعتبر كائن في النظام ويمكن تعريف متغريات من نوعها كما كنا نفعل مع القوائم أو الكائنات الأخرى
في السطر الثاني نقوم بتحميل القائمة albume من النافذة frm بقيم القائمة albume من النافذة الرئيسية
أي أن القائمة albume في النافذه الجديدة frm ستصبح نسخة مطابقة لقائمة albume الموجوده في النافذة الرئيسية
في السطر الثالث قمنا بإستدعاء الإجراء ShowDialog والذي يظهر النافذة frm للمستخدم
السطر الرابع يتم تنفيذة عند إغلاق النافذة frm , حيث يتم فيه نسخ قيمة albume من نافذة الألبومات لقائمة albume الموجوده في النافذة الرئيسية
أي ان الكود السابق يقوم بإنشاء نافذة جديدة وينسخ لها قيم albume حتى يعدل المستخدم فيها ويغلق النافذة
ثم يأخذ قيم albume من النافذة frm والتي تم تعديلها من قبل المستخدم وينسخ قيمها لقائمةalbume الموجوده في الصفحة الرئيسية
وفي السطر الخامس نستدعي إجراء FillList الذي يقوم بنسخ قيم albume إلى قائمة التشغيل كما شرحنا في الدروس السابقة
إذا شغلت البرنامج الآن وإخترت "التحكم بالألبومات" فلن تظهر لك عناصر قائمة albume لأنك لم تقم بإستدعاء إجراء تعبئة المستعرض FillView
حيث يحب إستدعاؤة بمجر تحميل نافذة الألبومات
إذهب إلى تصميم نافذة الألبومات وانقر مزدوجا على مكان خالي من الأدوات في النافذة ستنتقل إلى إجراة حدث Load :

void AlbumesLoad(object sender, System.EventArgs e)
{

}

أكتب إستدعاء إجراء تعبئة المستعرض بين الحاصرتين حتى يصبح الإجراء هكذا :

void AlbumesLoad(object sender, System.EventArgs e)
{
FillView();
}

شغل البرنامج ومن النافذة الرئيسية إختر مجموعة ملفات ثم إختر "التحكم بالألبومات" وجرب كل الوظائف.

الواجب
أرسل التطبيق
.نهاية الدرس العاشر.
..
.