yuval k

New member
Zeliran ידידי!

הרשה לי לנחש: בדוגמה שצירפת, ה-nodes שאתה מוסיף מוצגים רק כשאתה מריץ את האפליקציה אח"כ... יש אצלך בעיה בהבנה של איך הדברים פועלים, ולכן גם הבעיה שלך קורית. בדוט נט, כל טופס הוא בעצם קלאס שיורש מ-System.Windows.Forms.Form. כל מופע של מחלקת הטופס מהווה מופע של הטופס על המסך. מה שאתה עשית, זה הגדרת טופס כלשהו, נגיד - טופס א', עם כפתור להוספת nodes לעץ שבטופס ב'. טופס א' מאתחל מופע של טופס ב', וטוען לעץ שמוגדר במחלקה כלשהי, בצורה סטאטית, את המידע ששמרת ע"י serialisation. טופס ב', בעת איתחולו, טוען לעץ שעליו את אותו המידע. טעות ראשונה: העץ שהוגדר כסטאטי מהמחלקה השניה לא נחוץ כלל, העץ שייך לטופס שמציג אותו. אם אתה מחליט כבר להשאיר אותו, לשם המטרה הלימודית, אז למה שתטען מחדש מהקובץ אם כבר יש לך את המידע בעץ אחר? למה לא להעביר ממנו? בעת לחיצה על כפתור הוספת הצומת (node) לעץ בטופס א', אתה מבצע את הפעולה הבאה: 1. ייצור instance חדש של טופס ב'. 2. הוספת הצומת לעץ שבמחלקה הסטאטית, ושמירה. 3. ניקוי העץ בטופס ב' - במופע החדש שהגדרת. 4. טעינה מהקובץ, שאליו שמרת לפי העץ הסטאטי. 5. היפטרות מהטופס שייצרת. בשלב הזה נשארת עם המופע של טופס ב' שייצרת בהתחלת הריצה של התוכנית שלך. טעות שנייה: כשאתה מייצר instance חדש של הטופס, הוא לא קשור למופעים הקיימים של הטופס. כל פעולה שאתה מבצע עליו לא תחול גם על הטופס הקיים.
פיתרון הבעיה את המשתנה שאיתו אתה מגדיר את המופע של טופס ב' בתחילת הריצה תגדיר כמשתנה private של מחלקת טופס א', וכשאתה רוצה לבצע עליו את הפעולה, תפנה אליו - ולא דרך הגדרת מופע חדש וטיפול בו. אני גם הייתי מוותר על העץ הסטאטי, כי אפילו שהוא שם למטרה לימודית (כפי שאני משער), אין בו שום טעם, והוא סתם תופס זיכרון. חוץ מזה, מדוע אתה עובד במצב Release ולא Debug, כשעוד יש לך בעיות בתוכנה?
 

Zeliran

New member
האמתי.. שכן

קודם כל תודה ענקית להסבר המקיך של יובל.. באמת הזכרת לי כמה וכמה דברים שכבר הספקתי לשכוח, אז באמת תודה. אבל לצערי, הבעיה עדיין לא נפתרה.. זה מה שעשיתי: יצרתי אינסטנס פרטי של טופס ב' באתחול של טופס א' הסרתי את העץ הסטטי מהמחלקה השניה עכשיו כשאני רוצה להוסיף node חדש אני פונה לאינסטנס הפרטי ואני מוסיף אליו את ה node החדש אחר כך אני שומר את האינסטנס הפרטי אז אני עושה clear לאינסטנס הפרטי ובסוף אני טוען מהקובץ אל האינסטנס הפרטי.. אבל עדיין העץ שבטופס ב' לא מתעדכן, ונדרשת הפעלה מחדש של התוכנית כדי שהעץ יטען את הנתונים מהקובץ מה פספסתי? (ושוב תודה
)
 

yuval k

New member
איך הקוד נראה אצלך?

כששיניתי את הקוד לזה -
private frmTree m_ft; ... private void btnAdd_Click(object sender, System.EventArgs e) { clsTree.TREE.Nodes.Add (new TreeNode(txtName.Text)); LoadSaveTree.saveTree(clsTree.TREE, "nodes.dat"); m_ft.tv.Nodes.Clear(); LoadSaveTree.loadTree(m_ft.tv, "nodes.dat"); }​
זה עבד אצלי... (אתה יכול גם לכתוב ישר m_ft.tv במקום clsTree.TREE)
 

Zeliran

New member
אז ככה..

מסתבר שהתבלבלתי ביצירת האינסטנס במקום private frmTree ft כתבתי private frmTree ft = new frmTree מה ההבדל בעצם? בכל מקרה.. עכשיו זה עדיין לא עובד עכשיו, ששיניתי את הצורה שאני יוצר את האינסטנס, כל פעם שאני פונה אליו לכל פקודה שהיא, אני מקבל את השגיאה Object reference not set to an instance of an object. והשורה של ההכרזה על האינסטנס נצבעת עם קו כחול.. ואומרים שהוא not asssignd.. אבל בעצם התוכנית עוברת קימפול.. ורק ברגע שהתוכנית משתמש באינסטנס אז אני מקבל את השגיעה..
 

yuval k

New member
אתה צריך לאתחל אותו, כמובן.

אבל לא בהגדרת המשתנה, אלא ב-constructor (איפה שאתה כבר מגדיר...)
 

Zeliran

New member
?

לא הבנתי.. אז רגע.. אני יוצר אותו איפה שאני יוצר את כל הקונטרולס לטופס.. מה אני צריך להוסיף ואיפה?
 

yuval k

New member
תשאיר כמו בהודעה הקודמת,

וב-constructor -
public Form1() { ... m_ft = new frmTree(); m_ft.Show(); ... }​
 

Zeliran

New member
עובד! ../images/Emo13.gif אבל מה בדיוק עשינו כאן?

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

Zeliran

New member
גררר!!! ../images/Emo10.gif

בפרויקט החדש שיצרתי במיוחד כדי להראות כאן מה הבעיה.. עכשיו הכל עובד כמו שצריך.. כאשר העברתי את השינויים לפרוייקט שעכשיו אני עובד עליו, זה לא עובד! אני די בטוח ששיניתי הכל כמו שצריך.. ואני ממש לא מבין מה קורה כאן.. ההבדלים היחידים הם שיש טופס MDIPparent שפותח בהתחלה טופס עם treeView וגם עוד טופס אחר.. הטופס האחר פותח עוד טופס שגם הוא MDIChild (הטופס הזה הוא בדיוק כמו טופס א' בדוגמה שנתנתי) אבל כאשר אני מיסם את מה שאמרת לי לעשות בפוריקט הזה.. זה לא עובד.. מה יכול להיות ששכחתי כאן??
 

Zeliran

New member
זאת הבעיה..

אין לי מושג מה הולך כאן כי בעצם העתקתי את מה שעשיתי מהתוכנית לפרויקט הזה.. הגדרתי private frmTree ft ובקונסטרקטור עשיתי לו את ה new ואני משתמש באותן הפקודות שבהם השתמשתי בתוכנית השניה (בevent של ההוספה) וכשאני מנסה להוסיף node אז פשוט שום דבר לא קורה.. בדקתי איזה מיליון פעמים ואני לא מצליח למצוא הבדלים..
 

yuval k

New member
תסתכל טוב על שמות המשתנים...

ב-event handler של לחיצה על הכפתור אתה לא צריך לאתחל את האובייקט, פשוט להוסיף לו...
 

Zeliran

New member
אז זהו ש..

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

Zeliran

New member
נדמה לי שמצאתי את הסיבה לבעיה

אז כנראה זה לא קשור לקוד ששינתי.. הוא בסדר הבעיה היא כנראה ה MDI.. כי שלקחתי את התוכנית שעובדת, הוספתי עוד טופס שהוא MDIContainer ובקונסטרקטור שלו פתחתי את סני הטפסים ככה:
ft = new frmTree(); f1 = new Form1(); ft.MdiParent = this; f1.MdiParent = this; ft.Show(); f1.Show();​
(f1 ו ft מוגדרים כ private.. הם כבר מוכרזים..) אז יש לי את אותה הבעיה.. כשאני לוחץ על להוסיף node שום דבר לא קורה...אבל כשאני מפעיל מחדש את התוכנית, אז מתווספים ה nodes
 

yuval k

New member
והתשובה היא...

אתה יוצר עוד אובייקט שהוא frmTree ב-f1 שלך. זה שגם לו קוראים ft זה לא משנה: הוא במחלקה אחרת... אתה צריך להוסיף ישירות ל-instance של ft שמוגדר כ-MDI Child. כלומר, להעביר אותו ל-frmTree (למשל דרך הקונסטרקטור), ולקרוא לו - במקום לאתחל אותו שם מחדש. אם לא שמת לב עדיין... יש לך שני טפסים בשורת המשימות. אחד מהם זה ה-MDI Parent והשני הוא הטופס שאתה יוצר ללא-צורך
 

Zeliran

New member
עובד, אבל לא נדמה לי כמו שצריך..

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

yuval k

New member
?

אתה צריך ליצור את הטופס שמוסיף לעץ שלך ואת הטופס עם העץ יחד דרך ה-MDI Parent שלך, כמו עכשיו, ולהעביר לטופס שמוסיף לעץ את המשתנה שמכיל את הטופס של העץ (הוא עובר כ-reference אליו, ופעולה שתגדיר עליו תתבצע על הטופס המקורי). אתה לא צריך להגדיר מחדש שום טופס-עץ דרך טופס ההוספה לעץ.
 
למעלה