• الإعلانات

    • فيصل الحربي

      تسجيل عضوية جديدة في المنتدى   01/31/2016

      السلام عليكم ورحمة الله وبركاته  عزيزي العضو الجديد :  حاليا رسالة الإيميل لتأكيد صحة إيميلكم تذهب للبريد العشوائي ( جاري حل المشكلة )  فإذا لم تجد رسالة التحقق من إيميلكم في صندوق الوارد لديكم إتجه للبريد العشوائي ( JUNK)  وقم بتفعيل إشتراككم من هناك   

bahaa1985

اعضاء
  • عدد المشاركات

    360
  • تاريخ الانضمام

  • تاريخ اخر زياره

السمعه بالموقع

40 عادي

عن bahaa1985

  • الرتبة
    عضو فعال
  • تاريخ الميلاد 01/01/1985

معلومات الملف الشخصي

  • الجنس ذكر
  • الدولة : مصر
  • اهتمامات البرمجة و القراءة

أحدث الزائرين لملفلك الشخصي

12,843 زياره للملف الشخصي
  1. فيه أداة اسمها web browser بتضيفيها للفورم و من الخصائص أو من الكود بتحددي عنوان الصفحة اللي المفروض الأداة دي تعرضها
  2. استخدم left join و right join
  3. ضبط تاريخ صلاحية المنتج ؟

    الحل هو ادخال تاريخ انتهاء الصلاحية في قاعدة البيانات و على البرنامج تنبيه المستخدم بالقطع التي ستنتهي صلاحيتها قريباً كي يعمل على بيعها أو التخلص منها.
  4. مالسبب في هذا الخطاً

    تأكد من جملة الاتصال بين مصدر بيانات التقرير و بين قاعدة البيانات
  5. الناتج عندي مختلف و لا أعرف السبب. اذا جعلت keys بقيم رقمية و ليست نصية (مثلاً 9 بدلا من "009") ستجد أن عناصر الhashtable قد رتبت بشكل تنازلي
  6. الفرق بين Dataset,Entity Framework,LINQtoSQL

    السلام عليكم .. هذه مقالة من كتاباتي عن LINQ to SQL http://arabteam2000-forum.com/index.php/topic/278038-شرحالتعامل-مع-قاعدة-البيانات-بإستخدام-linqtosql/#entry1340091
  7. بسم الله الرحمن الرحيم في هذه المقالة سأتعرض لموضوع مهم جداً يهم المطورين المبتدئين بشكل خاص حيث عليهم أن يدركوه جيداً .. خصوصاً أن بعض أسئلة الانترفيو تكون حوله .. إنه الفرق بين Reference Types و Value Types.... في عالم الدوت نت انواع البيانات هي ثلاث أنواع : Reference Types - Value Types - Pointer Types .. معظم إستخدامنا مع البيانات هو مع النوعين الاولين اما Pointer Types فهو يستخدم نادراً.   ما الفرق بينهما؟ لديك صديق طلب منك عدد الأمس من جريدة ما .. لديك خياران: الأول أن تبعث له على الإيميل عنوان URL لموقع الجريدة على الإنترنت، و الثاني أن تذهب لتقابله في مكان ما و تعطيه نسخة من الصحيفة الورقية من الجريدة .. بالتأكيد الحل الأول أسرع و أفضل و لكن في بعض الحالات قد ألجأ للحل الثاني .. لذا علينا أن نعرف عندما نريد أن ننشأ أنواع البيانات بأنفسنا هل نجعلها Reference أم Value .   عندما تستخدم Value Type فإن CLR يقوم بحجز مكان في جزء Stack من الذاكرة و هذا المكان يحتوي على نسخة من النوع لها قيمة (نسخة ورقية من الجريدة)، أما عندما تستخدم Reference Type فإنCLR سيحجز مكان في Heap لقيمة النوع و عنوان (أو مؤشر أو مرجع) في الجزء Stack(عنوان URL لموقع الجريدة). أنظر لهذا الكود: int x = 5;ReferenceType r_type = new ReferenceType();سيتم تخزين قيمة X في Stack .. أما قيمة الكائن r_type فستخزن في Heap و سيخزن عنوان لهذه القيمة في Stack.     و هنا قد يظهر سؤال: لماذا هذا التعقيد .. لماذا لا تكن البيانات كلها من نوع واحد؟ الإجابة أن إستخدامات كلاهما تختلف .. فالأنواع Value Types تسند لها قيمة محددة واحدة مثل: int i=4;boolean log=true;أما النوع Reference Types فهو قد يحتوي على مجموعة بيانات مركبة و معقدة و من الصعب وضعها جميعاً في مكان واحد في Stack، لذا فهي تخزن في Heap و يخزن العنوان او المرجع لهذه البيانات في Stack، و الإعتماد على هذه التقنية أسرع في المعالجة لذا عندما تريد إنشاء فئة ستقوم مثلاً بإجراء عمليات معينة على قاعة بيانات أو فئة تقوم بعمل مصفوفة تستقبل بيانات من أنواع مختلفة فلابد من جعل فئتك Reference Type، أما إذا كنت تريد إنشاء فئة تعرض فقط مجموعة إختيارات  (ذكر/ أنثى) مثلا فهنا تستخدم فئة Value Type.   من الفروق الأخرى بينهما أن إنشاء فئة من نوع Reference Type يكون عن طريق كلمة class و النوع Value Type عن طريق كلمة struct: public class ReferenceType{ public int Field { get; set; } } public struct ValueType{ public int Field { get; set; }}فرق آخر بينهما، النوع Reference Type يرث من System.Object اما Value Type فهو يرث من System.ValueType التي ترث بدورها System.Object.   لمزيد من الفهم عن النوعين ننظر لهذا المثال: class Program { static void Main(string[] args) { Console.WriteLine("Reference Type:"); ReferenceType r_type1 = new ReferenceType(); ReferenceType r_type2 = new ReferenceType(); Console.WriteLine(r_type1.Equals(r_type2)); Console.WriteLine("Value Type:"); ValueType val1 = new ValueType(); ValueType val2 = new ValueType(); Console.WriteLine(val1.Equals(val2)); Console.ReadLine(); } } public class ReferenceType { } public struct ValueType { }Equals method هي وسيلة للتأكد ما إذا كان كائنين مساويين لبعض و هي ترجع true إذا كان الكائنين متساويين أو false إذا كانا غير ذلك .. قد يتبادر إلى ذهنك ان ناتج جملة Console.WriteLine الأولى سيكون true و الثانية ايضاً true، و لكن الحقيقة أن الأولى ستكون false لماذا ؟؟ لأن كلاً من r_type1 و r_type2 لهما reference مختلف في Stack، فكلاهما يشير لموضع قيم مختلفة في Heap. أما جملة Console.WriteLine الثانية فناتجها هو true لأن الوسيلة Equals هنا تقارن بين القيمتين بشكل مباشر و قيمة val1 و val2 متساويتين.   فللنظر لهذا المثال أيضاً: class Program { static void Main(string[] args) { Console.WriteLine("Reference Type:"); ReferenceType r_type1 = new ReferenceType(); ReferenceType r_type2 = r_type1; Console.WriteLine(r_type1.Equals(r_type2)); Console.WriteLine("Value Type:"); ValueType val1 = new ValueType(); ValueType val2 = val1 ; Console.WriteLine(val1.Equals(val2)); Console.ReadLine(); } }هنا سنجد ناتج الجملتين true .. لأن ReferenceType r_type2 = r_type1 معناها أن مرجع r_type2 هو نفسه مرجع r_type1، أي أن CLR قام بنسخ مرجع r_type1 و أعطاه لr_type2، إذن كلاهما يشير لنفس القيمة في Heap.   لتوضيح الفكرة السابقة نستعرض هذا المثال: class Program { static void Main(string[] args) { ReferenceType r_type1 = new ReferenceType();            ReferenceType r_type2 = r_type1;            Console.WriteLine("Before:");            Console.WriteLine(r_type1.r_field);            r_type2.r_field = 5;            Console.WriteLine("After:");            Console.WriteLine(r_type1.r_field);            Console.ReadLine(); } } public class ReferenceType { public int r_field { get; set; } }عند تنفيذ الكود سنجد ان ناتج سطر Console.Writeline الأول هو 0 و الثاني هو 5 .. لماذا؟ لأننا أخبرنا البرنامج ان مرجع r_type1 هو نفسه مرجع r_type2 و لم نكن قد أعطينا بعد أي قيمة للخاصية r_field في الكائن r_type2 .. لذا فقيمة الخاصية r_field في الكائن r_type1 هي القيمة القياسية 0، ثم أعطينا القيمة 5 لr_field  في الكائن r_type2، و لأن مرجعي الكائنين هما متساويين فهما يشيران لنفس القيمة، لذا سنجد ان مرجع r_type1 يشير للقيمة 5 أيضاً و بالتالي ستكون قيمة الخاصية r_field في r_type1 هي 5 أيضاً برغم أننا لم نعطها أي قيمة.     لنرى هل يمكن تطبيق نفس الفكرة على الأنواع ValueType: class Program { static void Main(string[] args) { Console.WriteLine("Before:"); ValueType val1 = new ValueType(); ValueType val2 = val1; Console.WriteLine(val1.v_field ); Console.WriteLine("After:"); val2.v_field = 5; Console.WriteLine(val1.v_field); Console.ReadLine(); } } public struct ValueType { public int v_field { get; set; } }هنا سنجد ان ناتج تنفيذ البرنامج هو 0 في المرتين، لأنك عندما تنشئ كائنات من النوع ValueType فإنك تنشئ نسخ من الفئة الأصلية و كل نسخة مستقلة عن الأخرى فمهما تغيرت قيمة الخاصية v_field في الكائن val2 فلن تتغير نظيرتها في الكائن val1     من الفروق الأخرى أن النوع ValueType لا يمكن الوراثة منه، اما Reference Type فيمكن ذلك.
  8. عمل method

    هذا ليس method و لكن event .... قم بإضافة المكتبة System.windows.Forms حيث أن KeyPressEventArgs موجودة في هذه المكتبة.
  9. Start>All programs>SqlServer 2008>Configuration Tools>Sql Server Configuration manager ثم إبحث عن client protocols و Protocols for ms sql server  و قم بعمل enabled لـtcp/ip و named pipes
  10. قم بوضع textbox في الفورم ثم أجعل قيمة الخاصية AutoCompleteMode تساوي SuggestAppend و الخاصية AutoCompleteSource تساوي CustomSource ثم ضع الكود التالي في حدث تحميل الفورم: List<string> my_list = new List<string>(); my_list.Add("محمد"); my_list.Add("أشرف"); my_list.Add("أحمد"); my_list.Add("مهند"); my_list.Add("كمال"); my_list.Add("سعيد"); my_list.Add("كامل"); my_list.Add("ملك"); my_list.Add("سيد"); my_list.Add("منى"); AutoCompleteStringCollection auto_source = new AutoCompleteStringCollection(); auto_source.AddRange(my_list.ToArray()); Auto_textBox.AutoCompleteCustomSource = auto_source;
  11. حتى و لو كانت لا توجد شبكة قم بعمل Enabled لبروتوكول Tcp\Ip
  12. بناء الألعاب البسيطة بلغة Vb.net

    شكراً جزيلاً ..
  13. تطبيق بسيط بLINQTOSQL لمن يريد..قم فقط بتعديل جملة الإتصال في ملف config لتتوافق معك.LinqToSqlApplication.rar  
  14. السلام عليكم و رحمة الله و بركاته ... المرة السابقة إستخدمنا هذا الكود لملء الداتا جريد:   //Fill datagridview with voyages: var vlist = from v in inter_dc.Voyages_Tables join vtp in inter_dc.VoyageType_Tables on v.VoyageType_ID equals vtp.ID join c in inter_dc.Companies_Tables on v.Company_ID equals c.ID join p1 in inter_dc.Ports_Tables on v.DepartPort_ID equals p1.ID join p2 in inter_dc.Ports_Tables on v.ArrivalPort_ID equals p2.ID select new { ID = v.ID, VoNo = v.VoyageNo, Date = v.VoyageDateTime, DepartPort = p1.PortName, ArrivalPort = p2.PortName, VoCompany = c.CompanyName }; dataGridView1.DataSource = vlist; هنا ستواجهنا مشكلة حيث أن الخصائص {ID,VoNo,Date,DepartPort,ArrivalPort,VoCompany} من النوع المجهول Anonymous Type  و هذا النوع من الخصائص للقراءة فقط..لذا عند ربط الداتاجريد بهذه الخصائص فإننا لن يمكننا تعديل أي شئ في الداتاجريد. “Anonymous types provide a convenient way to encapsulate a set of read-only properties into a single object without having to first explicitly define a type.” لذا لمواجهة هذه المشكلة سنقوم بالآتي...سنقوم بعمل Class جديدة و نسميها VoyagesDetails و تطبق الواجهة INotifyPropertyChanged، ثم ننشئ الخصائص التي سنربطها بالداتاجريد .... أي سنجعل هذا الClass مشابه تماماً لClasses الموجودة في الملف InterClasses.designer.cs:   class VoyagesDetails:INotifyPropertyChanged { private int _ID; public int ID { get { return _ID; } set { _ID = value; OnPropertyChanged("ID"); } } private string _VoNo; public string VoNo { get { return _VoNo; } set { _VoNo = value; OnPropertyChanged("VoNo"); } } private DateTime _Date; public DateTime Date { get { return _Date; } set { _Date = value; OnPropertyChanged("Date"); } } private int _DepartPortID;        public int DepartPortID        {            get{return _DepartPortID ;}            set            {                _DepartPortID =value ;                OnPropertyChanged ("DepartPortID");            }        }  private int _ArrivalPortID;        public int ArrivalPortID        {            get { return _ArrivalPortID; }            set            {                _ArrivalPortID = value;                OnPropertyChanged("ArrivalPortID");            }        }  private int _CompanyID;        public int CompanyID        {            get { return _CompanyID; }            set            {                _CompanyID = value;                OnPropertyChanged("CompanyID");            }        } public event PropertyChangedEventHandler PropertyChanged; private void OnPropertyChanged(string propertyName) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } static InterClassesDataContext inter_dc = new InterClassesDataContext(); public List<VoyagesDetails> DatagridVoyagesFill() { List<VoyagesDetails> voy_list = new List<VoyagesDetails>(); var vlist = from v in inter_dc.Voyages_Tables join vt in inter_dc.VoyageType_Tables on v.VoyageType_ID equals vt.ID join c in inter_dc.Companies_Tables on v.Company_ID equals c.ID join p1 in inter_dc.Ports_Tables on v.DepartPort_ID equals p1.ID join p2 in inter_dc.Ports_Tables on v.ArrivalPort_ID equals p2.ID select new {  ID = v.ID, VoNo = v.VoyageNo, Date = v.VoyageDateTime, DepartPortID=v.DepartPort_ID,DepartPort=p1.PortName,ArrivalPortID=v.ArrivalPort_ID ,ArrivalPort = p2.PortName , VoCompany =c.CompanyName,CompanyID=v.Company_ID }; for (int i = 0; i < vlist.Count(); i++) { voy_list.Add (new VoyagesDetails { ID = vlist.First().ID,                            VoNo = vlist.First ().VoNo,                            Date = (DateTime)vlist.First().Date,                            DepartPortID =(int)vlist .First().DepartPortID ,                                                        ArrivalPortID =(int)vlist .First().ArrivalPortID ,                                                        CompanyID=(int)vlist .First ().CompanyID } ); } return voy_list; } }سيكون كود الربط هكذا:   //Fill datagridview with Voyages:VoyagesDetails vd = new VoyagesDetails(); dataGridView1.DataSource = vd.DatagridVoyagesFill();فلنجعل الداتاجريد تبدو أكثر إحترافاً، لذا نغير نوع الاعمدة التي ستعرض الشركة و مطاري الإقلاع و الهبوط إلى النوع DataGridViewComboBox، و يجب أن تكون الخاصية DataPropertyName في عمود الشركة CompanyID و عمود الإقلاع DepartPortID و عمود الوصول ArrivalPortID (لاحظ أن هذه خصائص VoyagesDetails)،و نضيف عمودين من النوع DataGridViewButton كأزرار للتعديل و الحذف، ثم نكتب هذا الكود لملئهم في الحدث Form1_Load():   //fill departport column IQueryable depart = from i in inter_dc.Ports_Tables select new { ID = i.ID, PortName = i.PortName }; DepartColumn.DataSource = depart; DepartColumn.DisplayMember = "PortName"; DepartColumn.ValueMember = "ID"; //// fill arrivalport column IQueryable arrival = from i in inter_dc.Ports_Table2s select new { ID = i.ID, PortName = i.PortName }; ArrivalColumn.DataSource = arrival; ArrivalColumn.DisplayMember = "PortName"; ArrivalColumn.ValueMember = "ID"; /// fill companies column IQueryable company = from c in inter_dc.Companies_Tables select new { ID = c.ID, CompanyName = c.CompanyName }; CompanyColumn.DataSource = company; CompanyColumn.DisplayMember = "CompanyName"; CompanyColumn.ValueMember = "ID"; سيكون شكل الداتاجريد هكذا: و الآن فلننظر إلى كود حفظ  الرحلة في جدول Voyages_Table في قاعدة البيانات أسفل زر الحفظ :   Voyages_Table vt = new Voyages_Table { VoyageNo = textBox1.Text, VoyageType_ID = (int)combo_voyagetype.SelectedValue, Company_ID = (int)combo_company.SelectedValue, VoyageDateTime = dateTimePicker1.Value, DepartPort_ID = (int)combo_depart.SelectedValue, ArrivalPort_ID = (int)combo_arrival.SelectedValue }; //save the list items to Voyage_Table in the real database: inter_dc.Voyages_Tables.InsertOnSubmit(vt); inter_dc.SubmitChanges(); MessageBox.Show("تم الحفظ بنجاح!", "", MessageBoxButtons.OK);قمنا بإنشاء الكائن vt من Voyages_Table، ثم أعطينا كل خاصية في الكائن vt القيمة المناسبة لها من الأدوات، و للحفظ في قاعدة البيانات إستخدمنا الوظيفة InsertOnSubmit()  الموجودة في الخاصية  Voyages_Tables مع تمرير المعامل vt لها، ثم لتفعيل التغيير في قاعدة البيانات إستخدمنا inter_dc.SubmitChanges();.   و الآن حان دور التعديل و الحذف .. سنضع  أكوادنا أسفل الحدث dataGridView1_CellContentClick لأننا سنتعامل مع زري التعديل و الحذف في الداتاجريد:   if (e.ColumnIndex == but_update.Index) { VoyagesDetails vd = (VoyagesDetails)dataGridView1.Rows[e.RowIndex].DataBoundItem; Voyages_Table vt_row = inter_dc.Voyages_Tables.ToList().ElementAt(e.RowIndex); vt_row.ArrivalPort_ID = vd.ArrivalPortID; vt_row.DepartPort_ID = vd.DepartPortID; vt_row.Company_ID = vd.CompanyID; inter_dc.SubmitChanges(); MessageBox.Show("تم التعديل بنجاح!", "", MessageBoxButtons.OK); } else if (e.ColumnIndex == but_delete.Index) { VoyagesDetails vd = (VoyagesDetails)dataGridView1.Rows[e.RowIndex].DataBoundItem; Voyages_Table vt = (from v in inter_dc.Voyages_Tables where v.ID == vd.ID select v).First (); inter_dc.Voyages_Tables.DeleteOnSubmit(vt); inter_dc.SubmitChanges(); MessageBox.Show("تم الحذف بنجاح!", "", MessageBoxButtons.OK); }هنا سيتضح عرض الواجهة INotifyPropertyChanged التي جعلنا VoyagesDetails تطبقها..في البداية أنشانا متغيراً من النوع VoyagesDetails و هذا المتغير قيمته تساوي عناصر الصف الذي إخترته في الداتاجريد.. لماذا قمنا بهذه الخطوة؟ لأننا ربطنا الداتاجريد بـVoyagesDetails Class، ثم أنشانا المتغير vt_row من النوعVoyages_Table و قيمته تساوي صف محدد على أساس قيمة ID من جدول Voyages_Table. إذا إخترت مثلاً شركة الإتحاد بدلاً من مصر للطيران و مطار الوصول أبو ظبي بدلاً من مطار الدوحة فإن قيم خاصيتي CompanyID و DepartPortID الموجودتان في الـVoyagesDetails ستتغيران..هذا هو سبب إستخدامنا للواجهة INotifyPropertyChanged..أنها تقوم بإشعارك بالتغير في قيمة الخصائص، لذا قمنا بجعل قيم الخصائص المطلوب تعديلها في Voyages_Table تساوي الخصائص المعدلة في  VoyagesDetails(قم بوضع breakpoint و راقب تغير قيمة خصائص vd ) ، و لتطبيق التعديلات على الجدول في قاعدة البيانات نستخدم الوظيفة inter_dc.SubmitChanges(). في كود الحذف قمنا بإختيار الصف المطلوب حذفه من جدول Voyages_Tables، ثم تطبيق الحذف بإستخدام الوظيفة  inter_dc.SubmitChanges(); --------------------------------------- الخلاصة: 1- LINQTOSQL هي لإستخدام تقنية LINQ للإستعلام من فئات في برنامجك..هذه الفئات تمثل الجداول في قاعدة بياناتك و تمثل الحقول كخصائص. 2-الفئة الرئيسية لديك هي الفئة الممثلة لقاعدة البيانات نفسها، حيث تقع فيها الخصائص التي قيمتها تساوي الجداول و الوظائف اللازمة للإضافة و التعديل و الحذف. 3- عند إستخدام فئة تطبق الواجهة INotifyPropertyChanged فإن أي تغير في قيمة خصائص هذه الفئة يظهر في الأدوات المرتبطة بهذه الخاصية. 4- ناتج إستعلام LINQ هو من النوع المجهول Anonymous Type. 5- إذا كنت تريد ربط الداتاجريد بإستعلام ناتج من عمل join لجدولين فالأفضل عمل Class خاص يحتوي على الحقول التي تريد عرضها على شكل خصائص مع تطبيق الواجهة INotifyPropertyChanged ثم ربط الداتاجريد بالـClass. أتمنى أن أكون قد وفقت في شرح تقنية LINQTOSQL، و أعتذر مسبقاً إذا كان هناك صعوبة في فهم بعض النقاط.. السلام عليكم و رحمة الله و بركاته..
  15. السلام عليكم و رحمة الله و بركاته.. فلنلق نظرة على أحد الـClasses و ليكن مثلاً  Ports_Table:   public partial class Ports_Table : INotifyPropertyChanging, INotifyPropertyChanged { private static PropertyChangingEventArgs emptyChangingEventArgs = new PropertyChangingEventArgs(String.Empty); private int _ID; private string _PortName; private EntitySet<Voyages_Table> _Voyages_Tables; private EntitySet<Voyages_Table> _Voyages_Tables1; #region Extensibility Method Definitions partial void OnLoaded(); partial void OnValidate(System.Data.Linq.ChangeAction action); partial void OnCreated(); partial void OnIDChanging(int value); partial void OnIDChanged(); partial void OnPortNameChanging(string value); partial void OnPortNameChanged(); #endregion public Ports_Table() { this._Voyages_Tables = new EntitySet<Voyages_Table>(new Action<Voyages_Table>(this.attach_Voyages_Tables), new Action<Voyages_Table>(this.detach_Voyages_Tables)); this._Voyages_Tables1 = new EntitySet<Voyages_Table>(new Action<Voyages_Table>(this.attach_Voyages_Tables1), new Action<Voyages_Table>(this.detach_Voyages_Tables1)); OnCreated(); } [Column(Storage="_ID", AutoSync=AutoSync.OnInsert, DbType="Int NOT NULL IDENTITY", IsPrimaryKey=true, IsDbGenerated=true)] public int ID { get { return this._ID; } set { if ((this._ID != value)) { this.OnIDChanging(value); this.SendPropertyChanging(); this._ID = value; this.SendPropertyChanged("ID"); this.OnIDChanged(); } } } [Column(Storage="_PortName", DbType="NVarChar(30)")] public string PortName { get { return this._PortName; } set { if ((this._PortName != value)) { this.OnPortNameChanging(value); this.SendPropertyChanging(); this._PortName = value; this.SendPropertyChanged("PortName"); this.OnPortNameChanged(); } } } [Association(Name="Ports_Table_Voyages_Table", Storage="_Voyages_Tables", ThisKey="ID", OtherKey="DepartPort_ID")] public EntitySet<Voyages_Table> Voyages_Tables { get { return this._Voyages_Tables; } set { this._Voyages_Tables.Assign(value); } } [Association(Name="Ports_Table_Voyages_Table1", Storage="_Voyages_Tables1", ThisKey="ID", OtherKey="ArrivalPort_ID")] public EntitySet<Voyages_Table> Voyages_Tables1 { get { return this._Voyages_Tables1; } set { this._Voyages_Tables1.Assign(value); } } public event PropertyChangingEventHandler PropertyChanging; public event PropertyChangedEventHandler PropertyChanged; protected virtual void SendPropertyChanging() { if ((this.PropertyChanging != null)) { this.PropertyChanging(this, emptyChangingEventArgs); } } protected virtual void SendPropertyChanged(String propertyName) { if ((this.PropertyChanged != null)) { this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } private void attach_Voyages_Tables(Voyages_Table entity) { this.SendPropertyChanging(); entity.Ports_Table = this; } private void detach_Voyages_Tables(Voyages_Table entity) { this.SendPropertyChanging(); entity.Ports_Table = null; } private void attach_Voyages_Tables1(Voyages_Table entity) { this.SendPropertyChanging(); entity.Ports_Table1 = this; } private void detach_Voyages_Tables1(Voyages_Table entity) { this.SendPropertyChanging(); entity.Ports_Table1 = null; } } نلاحظ في هذا الكود الآتي: 1-  أن هذا الـClass يطبق الواجهتين INotifyPropertyChanging, INotifyPropertyChanged، و هاتان الواجهتان توفران طرقاً لتنبيه الأدوات المرتبطة بالخصائص الموجودة في الـClass بتغير قيمة هذه الخصائص، فمثلاً لو لديك اداة ListBox و قمت بتعيين الخاصية DisplayMember لPortName و حدث تغير في قيمة PortName فإن التغيير في قيمة DisplayMember سيحدث فوراً و ستشاهده أمامك. 2-الحقول ID,Portname تمث في الـClass كخصائص. 3-أيضاً العلاقات مع جدول   Voyages_table ممثلة كخصائص. 4- الأحداث public event PropertyChangingEventHandler PropertyChanging/public event PropertyChangedEventHandler PropertyChanged مشتقة من الواجهتينINotifyPropertyChanging, INotifyPropertyChanged و هي تستغل من الوظيفتين ()SendPropertyChanged(),SendProperyChanging للتنبيه بتغير قيمة الخاصية. و هذا أحد دلائل قوة LINQTOSQL .. فأنت هنا تستخدم الجداول كـClasses التي تطبق الواجهتين INotifyPropertyChanging, INotifyPropertyChanged لإكتشاف التغير في قيمة الحقل بدون كتابة المزيد من الكود من أجل فحص هذا الت و الآن فلنقم بتجربة الكود عملياً .. لذا أضف للفورم DatagridView و 4 ComboBoxes و TextBox: 1- في البداية ننشئ  Object من InterClassesDataContext Class حيث أنه الـClass الرئيسي الذي يمثل قاعدة البيانات و من خلاله نقوم بالإستعلام و الإضافة و التعديل و الحذف في السجلات.   InterClassesDataContext inter_dc = new InterClassesDataContext(); 2- نقوم بملء Comboboxes في الحدث Form1_Load:   //fill the comboboxes: combo_depart.DataSource = inter_dc.Ports_Tables; combo_arrival.DataSource = inter_dc.Ports_Tables; combo_company.DataSource = inter_dc.Companies_Tables; combo_voyagetype.DataSource = inter_dc.VoyageType_Tables;لو قمت بعمل run للمشروع و إخترت مثلاً مطار الكويت كمطار الإقلاع فستجد أن مطار الوصول قد تغير و أصبح مطار الكويت هو الآخر..السبب في ذلك أن كلا الـComboboxes مرتبطان بالخاصية PortName  و تلك الخاصية تقع في الـPorts_table Class التي تطبق الواجهتين INotifyPropertyChanging, INotifyPropertyChanged، و لا داعي لتكرار شرحهما حتى لا أكون مملاً.. و لكن أعتقد انك فهمت فائدة هاتين الواجهتين و كيفية إستغلال الحدثين PropertyChanging/PropertyChanged لتنبيه الأدوات بتغير قيمة الخاصية المرتبطة بهم. طبعاً نحن لا نريد أن يكون الـComboboxes مرتبطان مع بعضهما البعض..لذا سنضطر للذهاب للملف InterClases.layout.dbml و إدراج الجدول Ports_Table مرة أخرى .. لأن هذا الجدول موجود من قبل فسيتم تسمية الجدول الجديد Ports_Table2 و سنلاحظ إضافة الخاصية Ports_Table2s لـInterClassesDataContext.. لذا سنقوم بملء  combo_arrival بهذا الكود: combo_arrival.DataSource = inter_dc.Ports_Table2s ;عند إختيار مطار الإقلاع فلن يكون هو نفسه مطار الوصول.. الآن سنقوم بكتابة كود LINQ في الحدث Form1_Load() للإستعلام عن الرحلات و عرض النتيجة في الداتاجريد: //Fill datagridview with voyages: var vlist = from v in inter_dc.Voyages_Tables join vtp in inter_dc.VoyageType_Tables on v.VoyageType_ID equals vtp.ID join c in inter_dc.Companies_Tables on v.Company_ID equals c.ID join p1 in inter_dc.Ports_Tables on v.DepartPort_ID equals p1.ID join p2 in inter_dc.Ports_Tables on v.ArrivalPort_ID equals p2.ID select new { ID = v.ID, VoNo = v.VoyageNo, Date = v.VoyageDateTime, DepartPort = p1.PortName, ArrivalPort = p2.PortName, VoCompany = c.CompanyName }; dataGridView1.DataSource = vlist;لمن يريد معرفة المزيد عن تقنية LINQ فيمكنه الإطلاع على هذا الموضوع :http://arabteam2000-forum.com/index.php/topic/245463-linq-to-everything/ و لكن الكود في هذا الموضوع بالفيجوال بيسك,, من يرغي في السي شارب فليبحث في جوجل و سيجد ضالته. ستكون نتيجة الإستعلام بLINQ هكذا:   كما تلاحظون ان عناوين الأعمدة هي نفسها أسماء خصائص Anonymous Type Vlist إذا أردنا جعل عناوين الأعمدة بالعربية نضيف أعمدة للداتا جريد و نعين الخاصية DataPropertyName للخاصية المناسبة لها في Vlist:   نكمل لاحقا إن شاء الله .. في المرة القادمة سنتعلم ملء الداتا جريد مع الإستفادة من الواجهتين  INotifyPropertyChanging, INotifyPropertyChanged و حفظ و تعديل و حذف السجلات..