PracticU

פקדי רשימה - List

בלי כתוביותעם כתוביות
PracticU › קורס WinForms - תוכנות רגילות בווינדוס › פקדי רשימה - List
מילון מושגים:
לולאה - מבנה בקרה שחוזר על קטע קוד שוב ושוב כל עוד תנאי מתקיים או עבור כל פריט באוסף.
חריגה - מצב שגיאה שמתרחש בזמן ריצת התוכנית ומפסיק את המהלך הרגיל, אלא אם הקוד תופס ומטפל בו.
אינדקס - מבנה במסד נתונים שמאיץ חיפוש ושליפה. גם מספר המציין מיקום של איבר במערך.
אירוע - התרחשות שהמערכת מזהה ויכולה להגיב לה, כמו לחיצת עכבר, הקשה או סיום פעולה.
מערך - מבנה נתונים שמאחסן אוסף ערכים מאותו סוג ברצף, שאפשר לגשת אליהם לפי מספר מיקום (אינדקס).
תמונה - קובץ גרפי המוצג על המסך. בהקשר של וירטואליזציה או Docker, תבנית מוכנה שממנה יוצרים מכונה או קונטיינר.
טופס - אזור בממשק שבו המשתמש מזין נתונים בשדות ושולח אותם, למשל טופס הרשמה או התחברות.

פקדי רשימה - List
השיעור עוסק ברכיבי רשימה ב-Windows Forms: ListBox, ComboBox, CheckedListBox ו-ListView. כולם מסוגלים להחזיק סדרה של פריטים, אבל כל אחד מציג אותם אחרת.
ListBox
1. הוספה דינמית: מוסיפים פריטים לאוסף Items בעזרת Add. בדוגמה משדה טקסט ולחצן מתווספות מטלות לרשימה, והשדה מתנקה ומקבל פוקוס מחדש.
2. ניקוי: Items.Clear() מרוקן את הרשימה.
3. מצב בחירה (SelectionMode): None לא מאפשר בחירה, One מאפשר פריט אחד, MultiSimple מאפשר בחירה ובטול בחירה בלחיצה, ו-MultiExtended מאפשר Ctrl ו-Shift לבחירה מרובה. MultiExtended הוא הנפוץ ביותר.
4. הצגת הכול ו-הבחור: לולאה על Items מציגה את כל הפריטים, ולולאה על SelectedItems מציגה רק את הנבחרים.
5. מחיקה של פריטים נבחרים: הדובר הראה שמחיקה בתוך foreach על האוסף עצמו גורמת לחריגה, כי האוסף משתנה בזמן הריצה. לולאה קדימה על האינדקסים מדלגת על פריטים, כי האינדקס קופץ אחרי כל מחיקה. הפתרון: לולאה הפוכה, מהאחרון לראשון, עם Items.RemoveAt.
6. Remove מול RemoveAt: Remove מקבל את הפריט עצמו ומשווה אותו בעזרת Equals. RemoveAt מקבל מיקום.
ComboBox
1. הרכיב: שילוב של תיבת טקסט ורשימה נפתחת שמציגה פריט אחד בכל רגע.
2. DropDownStyle: DropDownList מונע מהמשתמש להקליד ערך משלו ומאפשר רק בחירה מהפריטים.
3. פריט דיפולטי: SelectedIndex = 0 בעת הטעינה, בונה פריט "Select Area" שמוצג מההתחלה.
4. בדיקה לפני שימוש: לפני קריאה לבחירה בודקים שהאינדקס גדול מאפס, כדי לא לקבל ערך לא חוקי.
5. אירוע: SelectedIndexChanged הוא האירוע הדיפולטי.
CheckedListBox
- כמו ListBox, אבל לכל פריט יש תיבת סימון.
- CheckedItems מחזיר את הפריטים המסומנים בלבד.
- התכונה CheckOnClick קובעת אם לחיצה אחת מסמנת את הפריט.
ListView
1. תצוגת Details: מציגה עמודות, והדובר מציג אותה דרך התכונה View.
2. עמודות: מוסיפים לאוסף Columns עם Text ורוחב (Width). DisplayIndex קובע את הסדר.
3. פריטים: יוצרים ListViewItem ממערך מחרוזות, כשכל איבר הוא ערך של עמודה, ומוסיפים ל-Items.
4. תכונות תצוגה: GridLines מציג קווי רשת, FullRowSelect מסמן את כל השורה בלחיצה, ו-BackColor צובע את השורה.
5. אייקונים: מוסיפים רכיב ImageList עם תמונות PNG, ומגדירים ב-SmallImageList. ImageIndex בפריט בוחר את התמונה. הדובר ציין שקבצי ICO לא נתמכים בייבוא לרכיב זה, ורק PNG ו-BMP נכונים.
6. קבוצות: מגדירים Groups ומשייכים כל פריט לקבוצה לפי אינדקס.
הצגת אובייקטים משלנו
ListBox ו-ListView מציגים את פלט ToString() של האובייקט. לכן מבצעים Override ל-ToString כדי להציג מידע מותאם. בנוסף, כדי להסיר אובייקט לפי הפריט עצמו, צריך לממש Equals בהתאם למאפיינים של המחלקה.
תרגילים
- טופס לאיסוף תחביבים לתוך ListBox.
- טופס לרשימת קניות עם ListView של שתי עמודות.
- טופס עם שם, מדינה (ComboBox) ועיר (ComboBox), שמציג את כל הערכים בתיבת הודעה אחת.
בסיום השיעור הסטודנט יודע לבחור את רכיב הרשימה המתאים, להוסיף ולמחוק פריטים בבטחה, ולהציג אובייקטים משלו ברשימות.
השיעור הבא בקורס: פקדי מיכל - Containers

פרקי ההרצאה: פקדי רשימה - List

  1. 00:00

    הכרת פקדי רשימה

  2. 00:47

    ListBox והוספת מטלות

  3. 02:16

    אוסף ה-Items והוספה

  4. 05:24

    הצגת כל הפריטים בלולאה

  5. 07:50

    מצבי בחירה SelectionMode

  6. 10:59

    מחיקת פריטים שנבחרו

  7. 16:43

    לולאה הפוכה למחיקה

  8. 19:04

    פקד ה-ComboBox

תמלול ההרצאה: פקדי רשימה - List

הטקסט המלא של הדקות הראשונות בהרצאה «פקדי רשימה - List» בקורס הווידאו של PracticU – כתוביות בעברית עם זמן התחלה לכל פסקה. כך תוכלו לקרוא ולחפש את הנושאים לפני שמתחילים ללמוד.

  1. 00:03

    אנחנו מגיעים לסדרת פקדים שמה שמשותף לכולם זה שהם מסוגלים להכיל רשימה של פריטים. אלו פקדי רשימה, ליסטינג. אז בואו נפתח פרויקט חדש, כמובן סוג Windows Forms Application, ואנחנו הולכים להסתכל על List Controls.

  2. 00:29

    כאן אנחנו הולכים להכיר סדרה של פקדים שמה שמאופיין בכולם זה שאנחנו יכולים להוסיף לכל אחד סדרה מסוימת של פריטים, ככה שהם יחזיקו ויראו את הפריטים כרשימה אחת.

  3. 00:43

    הרכיב הראשון שאנחנו הולכים לראות נקרא List Box. בואו נשים אותו, ובוא נניח שאני רוצה עכשיו להציג סדרה של מטלות.

  4. 00:57

    בואו נשים את זה כאן, ואני רוצה שתהיה לי את היכולת להוסיף מטלה, למחוק מטלה, להציג את כל המטלות, לבחור סדרת מטלות וכולי. קודם כל נקרא לרכיב הזה LST שזה קיצור של List Task מטלות, עכשיו בואו ניקח תיבת טקסט, ניקח לייבל ונוסיף מטלה חדשה.

  5. 01:36

    נגדיר שהלייבל הזאת היא lst-newtask, יש לנו פה תיבת טקסט txt-newtask, בואו נגדיל את זה, ניקח לחצן btn-addTask.

  6. 02:16

    אוקיי, מה אנחנו עכשיו צריכים לעשות? דבר ראשון, מה שאנחנו צריכים להבין זה שבכל רכיב שמסוגל להציג סדרה של פריטים, כמו הליסטבוקס הזאת, יש אוסף שנקרא Items בואו נסתכל עליו הנה אנחנו רואים אותו כאן קודם כל אנחנו יכולים כבר ב-Design Time לפתוח ולהוסיף כל מיני מטלות אם אנחנו רושמים את הדבר הזה אנחנו כבר רואים את המטלות או את הפריטים השונים לא

  7. 02:50

    משנה מה הם מוצגים לנו בתוך הליסט אבל אנחנו לא נוסיף כרגע מטלות בצורה סטטית אנחנו רוצים להוסיף בצורה דינמית יכולנו לעשות גם וגם כמובן מה אנחנו צריכים לעשות אנחנו צריכים לגשת בקוד לרכיב הליסט ושימו לב שרכיב הליסט יש לו את האוסף אייטמס ובאוסף אייטמס יש לנו פה את הפונקציות add, remove, clear וכולי.

  8. 03:27

    בואו נוסיף את txt.txt.newTask.text בצורה כזאת. הלייבל רק, שמתי לב שהתחילית שלה צריכה להיות מובן lbl.newTask.

  9. 03:43

    בואו נריץ, מטלה ראשונה do something, נוסיף. מטלה שנייה do something else, נוסיף. ואנחנו יכולים לראות גם שאנחנו יכולים להוסיף הרבה ערכים בצורה כזאת.

  10. 04:06

    כל מה שאנחנו מוסיפים מופיע בתוך הליסט. אחלה. כנראה שאנחנו נרצה גם לנקוט את תיבת הטקסט, txt-newtext.clear ולשים בחזרה פוקוס בתוך תיבת הטקסט כך שהסמן יופיע מיידית בתוך תיבת הטקסט ויאפשר למשתמש להוסיף עוד מטלה חדשה בצורה כזאת.

  11. 04:37

    אוקיי, כמה דברים נוספים שיכולים להיות עבור ListBox. אם אנחנו רוצים לבצע איזשהו קליר ולנקות רכיב כזה, בואו ניקח לחצן, אז יש לנו צורך להגיע לליסט, אייטמס, אני קצת קליר, בואו נריץ,

  12. 05:12

    נוסיף כמה מטלות שאנחנו רוצים לצפות בהן, ונלחץ על הלחצן, כולם מתנקות. אוקיי, אם אנחנו רוצים להציג את כל המטלות, כל הפריטים שנמצאים בתוך הליסט בוקס, בואו ניקח לחצן, שואו אול, דאבל קליק, נגיע לקוד, ומה שאנחנו רוצים לעשות זה פשוט לרוץ ולאסוף את כל הפריטים, נניח לסטרינג אחת ואז להציג אותה.

  13. 06:01

    יש לנו פה סטרינג all, נרוץ ב-4 על list items count ונשרשר list items במיקום i. בואו נשרשר את זה עם איזושהי עבידת שורה. נציג את all, נבדוק את זה, נביא קצת תוכנית, נוסיף כמה מטלות, נבצע show all ואני רואה שפשוט רצתי על האוסף והצגתי את הכל.

  14. 06:46

    יכלנו גם לרוץ בלולעת for each כמובן. אין שום בעיה, כל פריט בליסט בוקס הוא בעצם אובג'ק, ולכן אנחנו יכולים פשוט לעשות two-string של הפריט.

  15. 07:02

    אנחנו יכולים לבצע, סליחה, לולעת for each. כרגע כל הפריטים הם סטרינג, אז אין לי בעיה לרוץ עם סטרינג. item in list task.items all, פלוס שווה, אפילו בואו נשרשר את מה שכתוב.

  16. 07:22

    בעצם פלוס שווה אייטם ונשרשר ירידת שורה. אין שום בעיה לרוץ עם for each על כל הפריטים של אותו האוסף. מעולה.

  17. 07:45

    עכשיו יש לנו יכולת לבצע בחירה של פריטים. בואו נסתכל מה זה אומר. בחירה של פריטים אומר שהמשתמש יכול לבצע בחירה פשוט עם קליק בצורה מסוימת על הפריטים עצמם ואנחנו רואים שיש לנו כאן איזשהו מאפיין שנקרא selection mode, כלומר המצב של הבחירה ויש לנו כמה אופציות.

  18. 08:11

    one זה אומר שהמשתמש יכול לבחור פריט אחד none זה אומר שהמשתמש לא יכול לבצע שום בחירה של פריטים multi-simple זה אומר שהמשתמש לוחץ פעם אחת זה בחירה ופעם אחת זה ביטול בחירה multi-extended זה אומר שהמשתמש יכול להשתמש לצורך בחירה גם עם קונטרול וגם עם שיפט בואו נראה את multi-extended שהוא בדרך כלל הנפוץ ביותר

  19. 08:38

    אם אני רוצה לאפשר בחירה של מספר פריטים אני מריץ, אני מכניס ערכים ואני רואה שכשאני מסמן פריט אז הוא כמובן מתבצע סימון לגביו אבל אם אני עכשיו לוחץ על קונטרול וממשיך לסמן אני רואה שיש לי אפשרות גם לבחור מספר פריטים.

  20. 09:09

    מה זה השיפט? אם בחרתי פריט, לחצתי שיפט ובחרתי עוד אחד כל הפריטים מהפריט שנבחר עד אליו ייבחרו.

  21. 09:17

    זה ההבדל בין קונטרול שמאפשר בחירה בודדת לבין שיפט שמאפשר בחירה של סדרה של פריטים. עכשיו, אחרי שיש לנו את היכולת לבחור סדרה של פריטים, מה קורה אם אני רוצה ללכת ולהציג רק את הפריטים שנבחרו?

  22. 09:32

    אני רוצה שהמשתמש יוכל לבחור פריטים מסוימים, ואז לבצע איתם דבר מסוים. בואו ניקח פה לחצן נוסף, קרא לו btn show selected, אגדיל אותו טיפה בכדי לראות את הטקסט, אוקיי, ניקח את הקוד הקודם, נדביק, נוריד את עלולת ה-4 הזאת,

  23. 10:07

    אבל אנחנו לא נרוץ על אייטמס אלא נרוץ על סלקטד אייטמס זה ההבדל בואו לא נקרא לזה all נקרא לזה סלקטד נריץ נוסיף סדרה של פריטים נבצע בחירה של זה זה וזה 2 3 ו5 show selected ואנחנו רואים רק את 2 3 ו5 אחלה בואו נבצע דבר נוסף עם הפריטים שנבחרו בואו נניח שאנחנו רוצים לבצע מחיקה של הפריטים זה טיפה טריקי בואו נקרא ללחצן הזה btn

  24. 11:06

    delete selected למה אני טוען שזה טיפה טריקי בואו נסתכל דבר ראשון אם הייתי עכשיו רוצה לבצע מחיקה קודם כל איך אני בעצם יכול למחוק פריט אז יש לי שתי שיטות אני יכול לגשת לליסט אייטמס ויש לנו כאן רימוב ורימוב את רימוב את מוחק אינדקס מסוים אתם רואים שהוא מקבל את המיקום של הפריט ברשימה

  25. 11:47

    שהמיקום הראשון זה תמיד 0 ומוחק לי את הפריט שנמצא במיקום הזה. רימוב מקבל את הפריט עצמו. מקבל את הפריט עצמו ואז פונקציית רימוב רצה על כל הפריטים ומחפשת איפה הפריט נמצא.

  26. 12:03

    איך היא מבצעת את החיפוש? היא פשוט מנסה להשוות על ידי פונקציית equals. זאת אומרת שאם אנחנו לדוגמה מוסיפים פריטים שהם אובייקטים משלנו אז אנחנו כמובן הולכים לראות את ה-two-string שלהם, אולי תכף נעשה דוגמה כזאת, אבל כאשר אנחנו מבצעים מחיקה והמערכת מחפשת

  27. 12:23

    על ידי פונקציית equals את הפריט עצמו. אז יש לי שתי אפשרויות, או remove או remove at. אבל איך אני מוחק את הפריטים שסומנו? אז אם עכשיו אני בא ואני אומר דבר כזה, אני רץ ב-foreach string item in list task.selected, אני רוצה למחוק רק את הפריטים עצמם שסומנו ואני בא לליסט items.remove הרי יש לי את הפריט, הפריט זה אייטם ברשימה.

  28. 13:03

    מה שהולך לקרות אם אני אריץ את זה זה שאני אחטוף exception מהסיבה שאם אנחנו רצים על איזשהו קולקשן מסוים בלולת for each אסור לנו במהלך הריצה על הקולקשן לשנות את גודל הקולקשן.

  29. 13:21

    בואו נסתכל רגע מה יקרה אם אנחנו נריץ את זה. אז אני מריץ עם קונטרול F5 כרגע. בואו נוסיף סדרה של פריטים. בואו נסמן את זה, את זה ואת זה.

  30. 13:40

    ונבצע delete. ואנחנו רואים שיש לנו פה איזושהי exception. List that this enumerator is bound to has been modified. An enumerator can only be used if the list does not change.

  31. 13:56

    אוקיי. אז אסור לנו לרוץ עם לולת for h. אחלה. בואו נרוץ עם לולת for. אין בעיה.

  32. 14:03

    ואני הולך ומשנה את הקונספט הזה לקונספט של בואו נרוץ עם לולת for listTask.selectedItems.count זה רק המספר של הפריטים שנבחרו listTask.items.remove בואו נסיר את listTask.selectedItems במיקום i ואני טוען שהדבר הזה לא יעבוד בואו נסתכל אני מריץ נוסיף סדרה של פריטים, נסמן את 2, 3 ו-5.

  33. 15:00

    נבצע delete, ושימו לב מה סימנו, סימנו 2, 3 ו-5. אני רואה ש-2 נמחק, 3 לא נמחק ו-5 כן נמחק. כבר יש לנו פה איזשהו באג. אוקיי, אז מה בדיוק הבעיה?

  34. 15:20

    הבעיה היא שכאשר אנחנו ביצענו מחיקה, אז האוסף בעצם הצטמצם. אם האוסף הצטמצם, ומה אנחנו בעצם מחקנו? אנחנו סימנו את 2, 3 ו-5. אם אנחנו נצייר את זה, אנחנו נראה שהיה 1, 2, 3, 4, 5.

  35. 15:45

    זה מה שהיה. אנחנו סימנו את 2, 3 ו-5. 2 זה הדבר הראשון שהתגלה ונמחק, אבל אז האוסף הצטמצם והאינדקס של הלולאה, ה-i של הלולאה, קפץ.

  36. 16:01

    זאת אומרת שאם ה-i היה בהתחלה 0, אחר כך בוא נגיד היה לנו פה דבר כזה, היה 0, 1, 2, 3, 4. זה סומן ונמחק, i קפץ לבא בתור, ל-2, אבל עכשיו זה 1 וזה 2, זה כבר לא סומן, ולכן 3 בעצם התבצע דילוג מעליו.

  37. 16:32

    אז אנחנו רואים שאם אנחנו רוצים לבצע מחיקה של פריטים שסומנו, אנחנו צריכים לפעול בטכניקה קצת שונה. יש כל מיני לולאות שאנחנו יכולים להגדיר, אבל בטח לא לולאה שרצה קדימה, אז מה שנעשה זה פשוט נהפוך את הלולאה.

  38. 16:48

    ניקח לולאה שמתחילה ב-count -1, שזה בעצם הפריט האחרון, נכון? כי הפריטים מתחילים מ-0, אז הפריט האחרון יהיה מספר הפריטים פחות 1, נרוץ כל עוד i גדול שווה ל-0, נרוץ הפוך עם i מינוס מינוס, וניגש ונמחוק כעת את listTask.selectedItems במיקום i. בואו נבדוק את זה.

  39. 17:25

    נריץ את התוכנית, נכניס פה ערכים, ונסמן בדיוק את מה שסימנו מקודם 2 3 ו5 delete selected לכן 2 3 ו5 נמחקו הכל בסדר יכולנו לחילופין לעשות משהו קצת אחר ואפשר למחוק את ה-foreach שלא עובדת כמובן על שינוי אוסף אפשר לרוץ על selected indices ש-indice זה הרבים של אינדקס

  40. 18:03

    כלומר זה אוסף של המיקומים של הפריטים שנבחרו. אם אני רץ על המיקומים אז אני יכול להשתמש ב-remove at ואז אני יכול לגשת ל-selected indices במיקום i.

  41. 18:22

    זאתי שיטה נוספת שאני יכול לבצע מחיקה. remove at מקבלת אינדקס, הנה אנחנו נותנים לה את אחד האינדקסים של הפריטים שנמחקו או שסומנו ליתר דיוק. בואו נריץ, נוסיף בדיוק את אותם פריטים, נסמן את אותם פריטים ונבצע מחיקה.

  42. 18:38

    יש לנו פה אחד, שתיים, שלוש, ארבע וחמש. נסמן את שתיים, שלוש וחמש. delete. ובכן, מה שסימנו נמחק.

  43. 18:50

    אז בעצם אנחנו רואים שהצלחנו לעשות סדרה של פעולות נפוצות מאוד עם listbox. פקד הרשימה הבא שאנחנו הולכים לראות זה ה-combo box.

  44. 19:07

    פקד מאוד מפורסם, מה שהקומובוקס בעצם אומר זה שאנחנו יכולים להציג גם כן רשימה של פריטים אבל הרשימה תמיד מצטמצמת וניתן לראות רק פריט אחד ויחיד זאת אומרת אי אפשר לדוגמה לעשות פה בחירה מרובה אי אפשר לראות הרבה פריטים ולבחור במספר פריטים

  45. 19:29

    זה גם לא המטרה שלו, המטרה שלו זה להציג סדרה של פריטים שהיא תמיד תהיה מצומצמת וכל הזמן רואים רק פריט אחד שנבחר בואו נניח שאנחנו רוצים לאפשר למשתמש לבחור

לקורס המלא: קורס WinForms אונליין

ההרצאה הקודמת: רכיבים נפוצים - Common Controls

ההרצאה הבאה: פקדי מיכל - Containers

הרצאות קשורות מקורסים אחרים

  • הצגת רשימה - React List
  • List Dialog
  • list comprehension
  • רשימות - List - SharePoint

קורסים נוספים במסלול

  • פרויקט מעשי ב-#C - בונים מחשבון פשוט
  • פרויקט מעשי ב-#C - ספר טלפונים
  • פרויקט מעשי ב-#C - תוכנת צייר
  • קורס ADO.NET - חיבור אתר למסד נתונים
  • קורס תכנות מתקדם - #Advanced .NET C
  • קורס WCF - תקשורת למתקדמים בדוט-נט