Load Control

בטיטi

New member
../images/Emo26.gif Load Control

:ASP.NET 2.0 יש לי דף, שבתוכו יש 2 כפתורים, ופאנל. בפעם הראשונה שהדף עולה, הפאנל מציג טקסט "EMPTY". כשלוחצים על הכפתור הראשון, מתבצע LoadContol ל ascx מסויים (A), שנטען ומוצג בתוך הפאנל כשלוחצים על הכפתור השני, מתבצע LoadContol ל ascx אחר (B), שנטען ומוצג בתוך הפאנל (במקום הקודם) הכל עובד מצויין, לחיצה על כפתור א' מציגה בתוך הפאנל את קונטרול A, ולחיצה על כפתור ב' מציגה בתוך הפאנל את קונטרול B. הבעיה היא כאשר בתוך קונטרול, יש כפתור המבצע פוסטבק, במצב כזה, לחיצה עליו גורם לקונטרול להעלם, ומוצג EMPTY. כשחושבים על זה..
אז לחיצה על כפתור בתוך הקונטרול, גורם לפוסטבק למסך עצמו, ולכן הוא נטען שוב, ובמצבו הראשוני אכן מוצג EMPTY, מכיוון ששום קונטרול לא נטען עדיין.
חשבתי שבעת טעינת קונטרול, לשמור ב Session את שם הקונטרול שנטען, וב Page_Load של המסך, לטעון אותו שוב, אבל נראה לי עקום...
 
הרעיון שהצעת בסוף נכון

אתה *חייב* ליצור שוב את הקונטרול ב- PAGE_LOAD, וזה אפילו בלי קשר לבעייה שהצגת כאן. רק שלא הייתי שומר ב- SESSION אלא ב- VIEWSTATE, אבל זה תלוי בשאלה מה אתה רוצה שיראו אם יוצאים לעמוד אחר וחוזרים לעמוד הזה.
 

בטיטi

New member
נתקלתי בבעיה :

אפילו פישטתי את העניין : יש לי דף, ו User Control. על הדף יש כפתור, ופאנל. לחיצה על הכפתור, מריצה LoadControl לתוך הפאנל. ב Page_Load של הדף, גם מתבצע אותו דבר. התוצאה היא, שגם פוסטבק בתוך הקונטרול, עדיין משאירה אותו מוצג - מכיוון שהוא נטען שוב בעליית הדף. הבעיה היא מוזרה, כאשר לוחצים על כפתור בתוך הקונטרול, מתבצע פוסטבק, וכל הערכים בשדות (textbox למשל) שבתוך הקונטרול - נמחקים. הייתי מבין את זה, מכיוון שבעצם אני מבצע Load Control, הקונטרול נטען מחדש, ולכן כל הערכים נמחקים, אבל מה שמזר לי הוא : 1. אם מבצעים פוסטבק לדף, מזינים ערכים לקונטרול, ומבצעים פוסטבק לקונטרול - הערכים נמחקים 2. אם כעת ממשיכים, ומבצעים פוסטבק מתוך הקונטרול - הערכים נשמרים בטח בילבלתי אתכם לגמרי...
 

בטיטi

New member
בשמחה ! בבקשה :

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

נסה את זה:
protected void Page_Load(object sender, EventArgs e) { if (ViewState["ControlCreated"]!=null) { DynamicLoadControl(); } } protected void btnLoadControl_Click(object sender, EventArgs e) { DynamicLoadControl(); } private void DynamicLoadControl() { pnlContainer.Controls.Add(LoadControl("Details.ascx")); ViewState["ControlCreated"] = true; }​
זה לא קוד שבדקתי אותו, זה הכיוון הכללי של הפיתרון.
 
תשובה

זה מה שנקרא web application project ולא web site project ולכן אני לא יכול ממש לפתוח אותו כפי שאתה שלחת כי אין לי IDE מתאים. אבל איכשהו קימפלתי אותו ומה שחשוב זה ככה: בפעם הראשונה שהדף עולה אסור שתראה את היוזר קונטרוול שלך. אם אתה רואה אותו אז סימן שהוא נוצר ב- Page_Load, אבל בפעם הראשונה אסור לו להיווצר שם. אם הוא בכל זאת נוצר תבדוק למה. אחר כך אחרי שלוחצים על הכפתור העליון הקונטרול אמור להופיע. מהשלב הזה אסור ללחוץ שוב על הכפתור העליון, למעשה רצוי שתעלים אותו. כאשר ביצעתי את הדברים כך הכל עבד טוב. מה שכן היתה בעייה מוזרה שבהתחלה כששיניתי קוד עדיין ראיתי את הגירסא הישנה כי יש DLL של הפרוייקט בספרייה BIN. אני עובד עם Visual Web Developer 2005 ושם הפרוייקטים בנויים קצת אחרת, לכן אני לא בטוח האם זו בעייה אצלי או בעייה באופן כללי בפרוייקט שלך. עם איזה כלי בנית את הפרוייקט הזה? בשורה התחתונה: אם תלך לפי הכללים שלי מקודם זה יעבוד. למעשה זה בדיוק הקוד שכתבתי קודם, רק שצריך לוודא שזה באמת הקוד שאתה עובד איתו, ואם אתה רואה את הקונטרול שלך כבר הפעם הראשונה אז אתה עובד איכשהו עם קוד אחר.
 

בטיטi

New member
תגובה :

1. הזכרת את web application project ואת web site project, לכן אשמח אם תוכל להגיב כאן
בפעם הראשונה שהדף עולה, אני אכן לא רואה את היוזר קונטרול, וזה תקין. (מכיוון שהוא לא נוצר ב Page_Load של הדף), וביצוע פוסטבק בתוך הקונטרול אכן שומר על הערכים. הבעיה היא כאשר לוחצים שוב על הכפתור העליון, במצב כזה, הלחיצה הראשונה על הכפתור שבקונטרול מוחקת את הערכים, ואילו הלחיצות הבאות לא מוחקות אותם. (עד הפעם הבאה שלוחצים על הכפתור העליון). אני מניח שגם אתה נתקלת בכך, ולכן כתבת : "שלוחצים על הכפתור העליון הקונטרול אמור להופיע. מהשלב הזה אסור ללחוץ שוב על הכפתור העליון, למעשה רצוי שתעלים אותו" 2. אבל מדוע ? אתה יכול להסביר לי בבקשה את סדר הארועים הגורמים להתרחשות המוזרה הנ"ל ? 3. פרקטית, אני לא יכול להעלים את הכפתור, מכיוון שאני כן רוצה לאפשר לחיצה חוזרת עליו, בפועל יהיו מספר כפתורים, שישמשו כתפריט, ולחיצה על כל כפתור, תתען דינאמית יוזר קונטרול אחר...
 
תשובה

תחשוב מה קורה אחרי לחיצה שניה על הכפתור העליון: 1. נקרא האירוע Page_Load שיוצר את היוזר קונטרול. הקונטרול מקבל ID של ctl00. 2. נקרא האירוע btnLoadControl_Click שיוצר שוב את היוזר קונטרול. הקונטרול מקבל ID של ctl01. זהו הקונטרול שנשלח לדפדפן, והקונטרול הקודם נמחק (לפי הקוד המקורי שלך שאני שיניתי). מה שקורה בעצם קצת לא אינטואטיבי כי אם מחקת את הקונטרול הראשון כשניקית את ה- Childs של pnlContainer היית מצפה שהקונטרול השני יקבל אותו ID, אבל לא זה המצב ב- Asp.Net. עכשיו כאשר תלחץ על הכפתור הפנימי יתבצע Postback ובו הנתונים לגבי ctl01. אבל הפעם הקונטרול יווצר רק פעם אחת ויקבל ID של ctl00, כלומר לא תהיה התאמה בין הנתונים. פיתרון אפשרי:
private void DynamicLoadControl() { pnlContainer.Controls.Clear(); Control control = LoadControl("Details.ascx"); control.ID = "detailsCtrl"; pnlContainer.Controls.Add(control); ViewState["ControlCreated"] = true; }​
פיתרונות אחרים הם לא ליצור את הקונטרול פעמיים אם הוא הקונטרול שכבר בטופס, או לא לאפשר לחיצה על הכפתור העליון אם הקונטרול כבר נוצר (כי אין בזה טעם). אתה תוכל כמובן לאפשר לחיצה על כפתור אחר שיוצר קונטרול אחר. הכל תלוי מה אתה רוצה להשיג.
 

בטיטi

New member
../images/Emo45.gif../images/Emo51.gif../images/Emo70.gif שאלונת אחרונה :

תודה רבה על ההסבר והפתרון ! היה חשוב לי להבין את הבעיה בתהליך, כעת התופעה מובנת לי, תודה ! ולסיום, כמו שכתבתי בתגובה ל itzikbs : המטרה היא לבנות ממשק מעבר בין דפים צורה שקטה (ללא ריפרוש של הדף, כמו GMAIL), לכן הכוונה היא להפוך את כל הדפים בפרוייקט, ליוזר קונטרולים (כל דף יהפוך ל UC). כיצד אני מציע להשיג את הנ"ל ? ע"י משחקי LoadControl ? ע"י ההצעה של itzikbs של משחקי visible ? משהו אחר ? שוב תודה !
 
תשובה

זה לא מדוייק שבג'ימייל המעבר בין הדפים הוא בצורה שקטה. יש מקרים שכן ויש מקרים שמדובר בטעינה שלמה של הדף. אתו הדבר באפליקצייה שלך: לא הגיוני שכל האתר צריך להיות AJAX. יש דברים שכן ויש דברים שלא. אני לא בעד לשים הכל ביוזר קונטרולס ולשחק איתם, כי בסופו של דבר היוזר קונטרולס שלך יגדלו ויהיו בגודל של העמוד כולו, ואז זה אבסורד, כי אתה כאילו עושה אג'אקס אבל בפועל כל העמוד מתעדכן. כמובן שאם היוזר קונטרולס שלך הם חלק קטן מהעמוד ויש בינהם קשר לוגי הדוק אז זה אולי בסדר - הכל תלוי באפליקציה הספציפית שלך. לסיכום: פעולות שלא קשורות בכלל אחת לשניה, כמו ניהול ה- account לעומת שליחה לפורום (למשל) הייתי מציע לשים בעמודים נפרדים. בתוך הפורום אם צריך לפתוח הודעות ב- ajax או משהו מהסוג הזה, פה אפשר. משחקי היוזר קונטרול וה- visible טובים אם מדובר במספר קטן מאוד של יוזר קונטרולס, אבל לטווח ארוך קשה יותר לתחזק אותם. אני מציע לך לקרוא על Asp.Net Ajax (מה שבעבר כונה Atlas), זו הפלטפורמה החדשה של מיקרוסופט לביצוע Ajax (אם כי זה לוקח זמן להכיר את זה טוב, אז אם אתה צריך לבנות משהו מהר תחכה עם זה.)
 

בטיטi

New member
היי, תגובה :

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

אפילו בג'ימייל יש לפעמים Postback. גם מה שאתה מנסה להשיג לא בטוח בר השגה - אם הגולש עשה scroll לתחתית הדף ואז אתה מחליף לו את היוזר קונטרול הוא ירגיש את זה כמובן. ואם הוא לא עשה scroll אז בהנחה שיש לטופס side bar קבוע לכל user control, אפילו אם יהיה postback זה ייעשה מאוד מהיר. למעשה דפדפן כמו Firefox ידע לבד שה- side bar קבוע ולא ירנדר אותו מחדש. למשל תיכנס לבלוג הזה בפיירפוקס ותלחץ על הלינקים בצד ימין, תראה שבעצם לא כל הדף מצוייר מחדש. אולי אתה לא צריך Ajax אלא מה שנקרא Fajax, שזה fake ajax. תיכנס לכאן עם אקספלורר ושוב תלחץ על קישורים בצד ימין. אתה יכול גם לקרוא מה שכתוב שם על הנושא. לסיכום, אתה יכול בינתיים באמת לפתח את היוזר קונטרולס הנפרדים, ובסוף התהליך להחליט איך מתאים לך לתפור אותם ביחד. יכול להיות ששניים שלושה קונטרולים יתאימו באמת להיות בדף יחיד, אבל לא הייתי שם את כל האתר ככה. תחשוב שגם אולי אנשים ירצו לקשר לדף מסויים באתר ואם הכל זה אותו לינק אז יהיה קשה. בלי קשר אני לא מבין מה אתה מרוויח בשיטה הנוכחית, הרי הכפתור שלחיצה עליו יוצרת את היוזר קונטרול גורם postback (לאותו דף) אז לא מרוויחים כלום.
 

בטיטi

New member
רווח..

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

EdotK

New member
אז בדיוק כמו שהוא אמר לך. Fajax.

(ואתה יודע מה אני חושב על מה שאתה מנסה לעשות
)
 

itzikbs

New member
עבודה נכונה עם UC "דינאמיים"

מפאת קוצר הזמם והיריעה אני אשתדל לקצר, כאשר זקוקים לטעינה דינאמית של UC-ים הכוללים בתוכם PB (בד"כ זה כך ...)ובעמוד עצמו יש גם PB והעמוד (לאו דווקה עמוד אלא מה שנקרא TemplateControl כי זה בהחלט יכול להיות UC או CC המכיל בתוכו UC ...) עצמו מתחקר עובד מול ערכים מתוך ה UC השונים אזי צריך כמה כללים: 1. לעולם אל תשתמש במתודה "המסוכנת" LoadControl. במקום זאת : מקם את כל ה UC הרצויים באותו פנל, ושחק אם ה visibility שלהם במקום להשתמש בנ"ל,אין פה עניין של עומסים מכיון שהם לא מתרנדרים לדף. וכפי שאומר בהמשך אל תשים (!!!) שום פעולה בטעינה הראשונית שלהם 2. בנה חבילת ממשקים interfaces שבאמצעותם יתקשרו ה UC השונים עם הפקד האב שלהם (במקרה שלך העמוד) באמצעות אותם ממשקים תוכל להעביר ולקבל מידע - data בין הUC לעמוד. 3. חשוף במצעות אותם ממשקים, מתודות או מאפיינים האומרות ל UC מתי "להתחיל לעבוד" - בד"כ נניח לטעון מידע לגריד, רשימות שונות פעולות הפעלת WS וכל דבר אחר.... את כל הטעינה הנ"ל אל תשים ב Page_Load של ה UC !!! , שוב רק חשוף את הפעולות החוצה ורק כאשר העמוד מחליט להפעיל או להציג את ה UC אז תופעל המתודה הטוענת מידע ומבצעת פעולות. 4. שמור ב Cache מה שניתן ברמת כל UC - זה יהיה פשע. מה שנכתב פה מייצג נסיון עשיר ולאחר נסיונות והתייעצויות אין קץ באיך לעבוד נכון עם UC בצורה דינאמית, יעילה כאשר ה UC הינם מורכבים מאוד, בעלי אפשרויות רבות, אופציות תצוגה מגוונות ומלאות ב PB או CB- AJAX , אפשרות של כמה UC מאותו TYPE באותו עמוד, JS עצמאיים לכל אחד ועוד ... זהו . אני מקווה שזה לא מידי מסובך ולא הצלחתי לבלבל אותך (שוב הזמן קצר וההסבר והקונספט די מורכב ...) - אבל אם תעבוד בצורה זו, לא תצטרך אפילו לחשוב על VS או "יצירה מחדש" של ה UC מכיון שב ASP.NET ישנו מנגנון מובנה המנהל את ה VS של ו"יודע להציג בחזרה" לאחר כל PB את כל מה צריך. ביי איציק ב.
 

בטיטi

New member
תודה, תגובה:

1. מדוע LoadControl "מסוכן" ? 2. כלומר, הרעיון הבסיסי הוא להציב את כל ה UC בתוך הפאנל, ובכל פעם להציג רק את הרלוונטי ? 3. מדוע לבנות דרך תקשורת בין הדף לבין העמוד, ולא לשים את הפעולות ב Page_Load של הקונטרול ? הרי תמיד רק קונטרול אחד מתרנדר, ולכן רק ה Page_Load שלו יופעל... 4. ברמה העקרונית, המטרה היא לבנות ממשק מעבר בין דפים צורה שקטה (ללא ריפרוש של הדף, כמו GMAIL), לכן הכוונה היא להפוך את כל הדפים בפרוייקט, ליוזר קונטרולים (כל דף יהפוך ל UC), לכן לטעון את כולם לתוך הפאנל (ואס לשחק עם ה visible) נשמע קצת עמוס מידי, לא ? (אני הולך לטעון את כל הדפים (שכל אחד הוא בעצם UC) לתוך הפאנל...)
 
למעלה