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

عمل نموذج Master/Detail

بدأه محمد خليل أبو صلاح في 23 ديسمبر 2004 · 10 رد · 6,753 مشاهدة · في ASP.NET
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

موضوع جديد أكتبه لكم لعل البعض يستفيد منه و هو عن ال Master/Detail Form

الكثير من الأفكار خلال زيارتنا لعدد من المواقع و بعضها يكون ساكنا و بعضها يكون Dynamic و هو الذي يهمنا كما نرى في المنتديات و المجلات الإلكترونية و العديد من التطبيقات الشبكية المنتشرة هنا و هناك على شبكة الإنترنت.

لو نفرض أن هناك تصنيفات و تقع تحتها عدد من المشاركات إعتدنا رؤيتها كترتيب للتصنيفات و عند الضغط على إحدها يتوجه بنا المتصفح لصفحة تعرض المشاركات التي تقع تحت هذا التصنيف و هذا بالعادة نراه في المنتديات و لكن نرى بعد التطبيقات تعرض التصنيفات و تحتها المشاركات كلا على حدة و هذا رأيناه في مثال ذكرناه في درس ال DataView و أحيانا نرى التصنيفات مذكورة بشكل عادي و عند الضغط على أحدها تظهر مشاركات هذا التصنيف تحته مباشرة و عند الضغط على تصنيف آخر تختفي مشاركات التصنيف الأول و تظهر مشاركات التصنيف الجديد.

بالعادة هذه البيانات تحتاج لوجود جدولين بينهم علاقة من نوع 1-M أو ما يطلق عليها اسم one_to_many و تسمى النماذج Forms التي تعتمد على هذه الجداول بإسم Master/Detail Forms و سنأخذ مثالا يعرض التصنيفات داخل DataList على شكل وصلات و عند الضغط على إحداها ستظهر الدروس التابعة لهذا التصنيف بنفس الصفحة داخل Repeater.

لنرى بداية شكل الصفحة التي ستظهر لنا في هذا الشكل :

aspnet-datalist2.gif

الآن نأتي لتحليل الفكرة.

أولا نركز على ال DataList التي ستعرض التصنيفات و هذا الشيء اعتدنا عليه مرارا.

ثانيا نجعل أسماء التصنيفات عبارة عن وصلات تشعبية HyperLinks.

ثالثا نضيف حدث لل DataList عبارة عن ItemCommand.

رابعا نحدد ال DataKeyField و نجعله رقم التصنيف id و هو نفسه ال PK في الجدول.

خامسا عند الضغط على الوصلة أي التصنيف سوف يتم تنفيذ الحدث و بالتالي يتم تمرير رقم القسم له و الحدث يخص ربط ال Repeater بالبيانات حيث سيستغل رقم التصنيف ليجلب البيانات من جدول الدروس و يقوم بربطها بالأداة.

سادسا كل عنصر قمنا بإختياره و أقصد هنا التصنيف سوف يظهر بشكل عادي و ليس وصلة تشعبية من خلال الوسم SelectdItemTemplate.

نذكر الكود أولا ثم نقوم بتحليل أجزاءه :

<%@ Page Language="C#" Debug="True" %>
<%@ import Namespace="System.Data.OleDb" %>
<%@ import Namespace="System.Web.UI" %>
<%@ import Namespace="System.Web.UI.WebControls" %>
<script runat="server">

void BindDataList()
{

string prov="Provider=Microsoft.Jet.OleDb.4.0;Data Source=" + Server.MapPath("Library.mdb");
string SQL="SELECT * FROM Library_Categories";
OleDbConnection cn = new OleDbConnection(prov);
OleDbCommand cmd = new OleDbCommand(SQL,cn);


cn.Open();


OleDbDataReader reader = cmd.ExecuteReader();

dl.DataSource= reader;
dl.DataBind();

reader.Close();
cn.Close();
}

void BindRepeater(string intCatID)
{

string prov="Provider=Microsoft.Jet.OleDb.4.0;Data Source=" + Server.MapPath("Library.mdb");
string SQL="SELECT * FROM Library_Lessons where catID=@catID";
OleDbConnection cn = new OleDbConnection(prov);
OleDbCommand cmd = new OleDbCommand(SQL,cn);
cmd.Parameters.Add("@catID",intCatID);

cn.Open();


OleDbDataReader reader = cmd.ExecuteReader();

rp.DataSource= reader;
rp.DataBind();

reader.Close();
cn.Close();
}


void Page_Load()
{
if(!Page.IsPostBack)
{
BindDataList();
}


}

void dl_ItemCommand(Object source, DataListCommandEventArgs e) {
string intCatID;
dl.SelectedIndex=e.Item.ItemIndex;
BindDataList();
intCatID=dl.DataKeys[e.Item.ItemIndex>.ToString();
BindRepeater(intCatID);
}

</script>
<html>
<head>
</head>
<body>
<form runat="server">
<asp : DataList id="dl" runat="server" OnItemCommand="dl_ItemCommand" DataKeyField="id">
<EditItemStyle borderstyle="Solid" bordercolor="Gray"></EditItemStyle>
<ItemTemplate>
<asp:LinkButton Runat="server" Text='<%# DataBinder.Eval(Container.DataItem,"category")%>' />
</ItemTemplate>
<SelectedItemTemplate>
<i> <b><%# DataBinder.Eval(Container.DataItem,"category")%></b></i> 
</SelectedItemTemplate>
</asp : DataList>
<asp:Repeater id="rp" runat="server">
<ItemTemplate>
<p align="right">
<a href='more.aspx?id=<%# DataBinder.Eval(Container.DataItem,"id")%>'> <%# DataBinder.Eval(Container.DataItem,"title")%> </a> 
</ItemTemplate>
</asp:Repeater>
</form>
</body>
</html>

في منطقة الأكواد توجد أحداث و إجرائيات كالتالي :

BindDataList

BindRepeater

Page_Load

dl_ItemCommand

الأولى تقوم بربط أداة ال DataList مع البيانات المستخرجة من جدول التصنيفات و الثانية تقوم بربط ال Repeater بالدروس التابعة للتصنيف على حسب رقم التصنيف الممرر للإجرائية و الثالثة هي الحدث الخاص بتنفيذ تعليمات معينة عند تحميل الصفحة و الحدث الأخير يحدث في حال الضغط على أي وصلة من التصنيفات.

الآن نأتي لمنطقة ال HTML و نرى أننا أضفنا DataList كالتالي :

<asp : DataList id="dl" runat="server" OnItemCommand="dl_ItemCommand" DataKeyField="id">
<EditItemStyle borderstyle="Solid" bordercolor="Gray"></EditItemStyle>
<ItemTemplate>
<asp:LinkButton Runat="server" Text='<%# DataBinder.Eval(Container.DataItem,"category")%>' />
</ItemTemplate>
<SelectedItemTemplate>
<i> <b><%# DataBinder.Eval(Container.DataItem,"category")%></b></i> 
</SelectedItemTemplate>
</asp : DataList>

نرى أننا أضفنا خاصية OnItemCommand و التي تستدعي الحدث dl_ItemCommand عند الضغط على أي زر موجود داخل ال data list و أضفنا الخاصية DataKeyField لتحدد البيانات المميزة للسجل الذي اخترناه. ثم حددنا نمطا معينا للعنصر أو السجل الذي إخترناه من خلال EditItemStyle و بعد ذلك أضفنا الوسم ItemStyle و هو يعرض التصنيفات داخل LinkButton ثم أضفنا الوسم SelectedItem و الذي يعرض التصنيف الذي إخترناه و لكن بشكل عادي و خط مائل و عريض و ليس وصلة تشعبية كما كان في حالة ال ItemTemplate.

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

<asp:Repeater id="rp" runat="server">
<ItemTemplate>
<p align="right">
<a href='more.aspx?id=<%# DataBinder.Eval(Container.DataItem,"id")%>'> <%# DataBinder.Eval(Container.DataItem,"title")%> </a> 
</ItemTemplate>
</asp:Repeater>

الان نأتي لشرح الإجرائيات حسب تسلسل حدوثها.

void Page_Load()
{
if(!Page.IsPostBack)
{
BindDataList();
}

طبعا كلنا نعرف هذا الحدث حيث أنه في حال أول زيارة للصفحة يتم ربطها بالبيانات و أقصد هنا ال DataList التي ستعرض التصنيفات و ذلك من خلال إستدعاء الإجرائية BindDataList.

void BindDataList()
{

string prov="Provider=Microsoft.Jet.OleDb.4.0;Data Source=" + Server.MapPath("Library.mdb");
string SQL="SELECT * FROM Library_Categories";
OleDbConnection cn = new OleDbConnection(prov);
OleDbCommand cmd = new OleDbCommand(SQL,cn);


cn.Open();


OleDbDataReader reader = cmd.ExecuteReader();

dl.DataSource= reader;
dl.DataBind();

reader.Close();
cn.Close();
}

هذه الإجرائية شرحناها كثيرا ولا نحتاج لإعادة شرحها.

يفترض الآن أن تظهر البيانات أي التصنيفات في ال DataList و لكن ماذا سيحدث عند الضغط على إحداها ؟؟

أولا سوف يتحول العنصر من حالة ال ItemTemplate إلى ال SelectedItemTemplate و طبعا نكون ضغطنا نحن بالأصل على ال LinkButton و بالتالي فعلنا الحدث dl_ItemCommand و الذي به الكود التالي :

void dl_ItemCommand(Object source, DataListCommandEventArgs e) {
string intCatID;
dl.SelectedIndex=e.Item.ItemIndex;
BindDataList();
intCatID=dl.DataKeys[e.Item.ItemIndex>.ToString();
BindRepeater(intCatID);
}

نرى أننا عرفنا متغير نصي باسم intCatID و هو يحمل رقم التصنيف و جعلته من النوع string لسبب و هو أننا لو أردنا الحصول على رقم التصنيف من خلال الباراميتر e و الذي يحصل عليه من خلال خاصية ال DataList و هي ال DataKeyField فإن dl.DataKeys[e.Item.ItemIndex> سوف تعيد لنا الناتج من النوع Object لذا لجأنا للطريقة ToString لنحوله لنص. و قبلها جعلنا العنصر الذي إخترناه يدخل في حالة ال SelectedItemTemplate من خلال :

dl.SelectedIndex=e.Item.ItemIndex;

ثم قمنا بإستدعاء الإجرائية BindRepeater و مررنا لها رقم التصنيف و طبعا كلنا نعرف أن ال Repeater لا يظهر بيانات إلا عند ربطه بها و بالتالي حال إستدعاء الصفحة أول مرة لا تظهر لنا الدروس لأننا لم نختر أي تصنيف و أيضا لا تظهر البيانات في حال عدم وجود نتائج متطابقة مع جملة الإستعلام SQL أو مع ال DataView و هنا لم نستخدمها طبعا بل إستخدمنا جملة إستعلام فقط.

void BindRepeater(string intCatID)
{

string prov="Provider=Microsoft.Jet.OleDb.4.0;Data Source=" + Server.MapPath("Library.mdb");
string SQL="SELECT * FROM Library_Lessons where catID=@catID";
OleDbConnection cn = new OleDbConnection(prov);
OleDbCommand cmd = new OleDbCommand(SQL,cn);
cmd.Parameters.Add("@catID",intCatID);

cn.Open();


OleDbDataReader reader = cmd.ExecuteReader();

rp.DataSource= reader;
rp.DataBind();

reader.Close();
cn.Close();
}

كما نرى قمنا بعمل إتصال بقاعدة البيانات و استخدمنا إستعلاما مشروطا برقم التصنيف الذي مررناه ثم أنشأنا DataReader لجلب البيانات من جدول الدروس حسب رقم التصنيف الذي إخترناه و من ثم ربطناه بال Repeater و أغلقنا الإتصال.

كان هذا هو درسنا عن ال Master/Detail Forms و أتمنى أن تكونوا قد إستوعبتم هذا الدرس بكل سهولة فهو مهم للغاية.

محمد خليل أبو صلاح

aspnet-masterdetail.zip

You can fly while you can touch the sky

#2

ملاحظة : قاعدة البيانات غير مرفقة و يمكن استنتاج الحقول بكل سهولة من المثال.

تم تعديل هذه المشاركة بواسطة محمد خليل أبو صلاح في 24 ديسمبر 2004 في 00:28

You can fly while you can touch the sky

#3

أرفقت قاعدة البيانات لكم بالأكسيس :)

db.zip

You can fly while you can touch the sky

#4

شكرا اخي علي الجهد الرائع بل والاكثر من رائع

love36.jpg
#5

لك مني جزيل الشكر

#6

يعطيك العافيه

#7

السلام عليكم

بارك الله فيك

ولكن أثناء تصفحي بالأمس لمايكروسوفت رأيك موضوع يحمل نفس العنوان تقريبا وقمت بتحميله هل هو نفسه علشان أريح حالي وما أقراه ???

#8

نعم فكرة ال Master/Detail هي نفسها لن تختلف طالما ألممت بالفكرة الرئيسة و إن شاء الله بتستفيد :)

موفق

You can fly while you can touch the sky

#9

بارك الله فيك

الحمد لله الذي بنعمته تتم الصالحات

#10

جزاك الله خيرا

Oracle Developer

#11

الله اوفقك

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