קה פרובלמה מואי צ'יקיטה?
נשאלת השאלה הבאה: אם אתה רוצה שפעולת שינוי הטאב תהיה שקופה למשתמש או שהיא תדרוש PostBack? אם אתה רוצה שהיא תדרוש PostBack באמת תוכל לעבוד עם פקד MultiView וסט כפתורים שכל אחד מהם יגרום ל-ActiveViewIndex של ה-MultiView להשתנות בהתאם. ככה הלקוח בדפדפן שלו לוחץ על כפתור, הלחיצה על הכפתור רצה בחזרה לשרת עם כל הדף, משנה את ה-View הפעיל ב-MultiView והכל חוזר ללקוח מרונדר ויפה. השילוב בין ה-MultiView ובין הסט כפתורים שכל אחד מהם קובע אינדקס אחר ושונה מצדיק לשים את שניהם כחלק מפקד משותף (או Composite Control או User Control) ולהשתמש רק באחד מהם. הפקד עצמו לא מסובך מדי, אבל אם תבחר לכתוב אותו בקוד בלבד (Composite Control) אתה תאבד את היכולת להוסיף Templateים של קוד ASP.Net כ-Viewים. כדי להוסיף Viewים בצורה הזו תצטרך או לרשת את View וליצור את ה-Viewים שלך כ-Custom Controls או לחשוף מחדש יכולת לערוך Templateים. אם אתה רוצה שהפעולה לא תדרוש PostBack והפעולה תתבצע בצורה שקטה מהמשתמש יש לך כמה אפשרויות איך שאני רואה את זה. החלטה נוספת שבשלב הזה תצטרך לקבל הוא האם אתה מעוניין שכל ה-HTML לכל הטאבים ישלחו ללקוח או שאתה מעוניין שהלקוח ידבר עם השרת (בצורה שקטה) ויעביר כל פעם רק את ה-HTML הנדרש להצגה באותו רגע. אם החלטת לשלוח את כל ה-HTML וכל פעם להציג תוכן של טאב אחר אז אנחנו עכשיו פונים לג'אווה סקריפט. תיקח את כל התכנים השונים של כל הטאבים ותכניס כל אחד מהם ל-<div> נפרד (פקד Panel). בצד לקוח, יהיו אלמנטים סטטיים (כפתורים, קישורים, תמונות או כל דבר אחר) עם קישור לאירוע onclick של ג'אווה סקריפט. בלחיצה על הכפתור צד-לקוח <div> אחד יחשף וה-<div> שכרגע חשוף יוסתר. מדובר על קביעה פשוטה של this.style.visiability = none. כאשר הדף מאותחל יש לדאוג שיש בדיוק פקד Panel אחד שהוא עם visibility : inline וכל השאר עם visiability: none. עכשיו, זאת הייתה הדרך המקובלת לעבוד עד עכשיו. אישית, אני חושב שאפשר לעשות משהו הרבה יותר נקי. כן ללעבוד עם ג'אווה סקריפט, אבל לא ללערבב את ההתנהגות ואת הבנייה של הפקד צד-שרת בצורה חצי-גמורה כזו שבלתי אפשרי לתחזק. צריך ליצור פקד אחד כמו שצריך שעושה את כל העבודה הזאת ואפשר לעבוד מולו בצורה שקופה וקלה כמו שנהוג לעבוד מול רכיבים מקצועיים. ליצור אלמנט בשם Tab שיתרנדר לתגית <div> שבתוכה יהיה תוכן שיקלט מהמשתמש (או באמצעות מערך Controls פנימי או באמצעות חשיפת ITemplate שיאפשר הוספת קוד ASP.Net פנימי בעיצוב). ליצור אלמנט בשם Tabs שיכיל מערך של Tabים וירנדר את כולם לצד לקוח. בנוסף Tabs ירנדר גם מערך של כפתורים צד-לקוח שיהיו אחראים לאירוע onclick כמו שתיארנו לעיל. עכשיו אני אקח את זה עוד צעד קדימה - Microsoft AJAX. במקום לפזר את הג'אווה סקריפט בכל מקום (למשל לכתוב Onclick ברנדור של הכפתורים, למשל לקבוע visiability ברנדור צד-שרת, למשל להתחיל לדאוג לתאימות בין הדפדפנים של כל הסיפור הזה) אפשר לעשות משהו הרבה יותר פשוט. אפשר ליצור מה שנקרא Behavior צד-לקוח של Ajax. אותה Behavior עובדת על הקונספט הבא "אני למעשה מחלקה. אבל אני בצד-לקוח ואני בג'אווה סקריפט. אני יורשת ממחלקה בשם Behavior, יש לי קונסטרקטור ודיסקטרקטור, ואני יכולה לחשוף מאפיינים ואירועים, אני גם יכולה להירשם לאירועים של הדפדפן". התפקיד של Behavior כזה כאן לדעתי יהיה מאוד פשוט: להחזיק מערך של Tabים צד-לקוח (שזאת מחלקה צד-לקוח שגם נצטרך לכתוב) ומצביע לפעיל ביניהם. המחלקה צד-לקוח של Tab תאפשר לנו שני דברים: להעלים Tab ולגרום ל-Tab להופיע. באתחול של ה-Behvaior שלנו נעשה כמה דברים: נעלים את כל ה-Tabים, נקבע טאב פעיל (בין אם לפי קביעה של מאפיין צד-שרת או פשוט נבחר את ראשון), נגרום ל-Tab צד לקוח הראשון להיראות למשתמש, והכי חשוב - נירשם לאירוע ה-onclick של כל הכפתורים שלנו. תקשיב טוב מה נאמר כאן כרגע, נרשם לאירוע צד-לקוח. במתודה שנרשמה לאירוע צד-לקוח של onclick (ואותה מתודה להזכירך כתובה בג'אווה סקריפט צד-לקוח) תיקח את ה=Tabשמקושר לאותו כפתור ותשנה ב-Behavior את ה-Tab הפעיל (גם את המאפיין שחושף ה-Behavior, גם תעלים את ה-Tab הקודם וגם תגרום ל-Tab הזה להיראות). אפשר לקחת את זה עוד קדימה - למה בכלל לשלוח ללקוח את כל ה-HTML לכל הטאבים? באמצעות Ajax אפשר לפנות בנונ-שלנטיות של שורה שורת ג'אווה סקריפט אחת לשרת ולבקש ממנו את ה-HTML שאליו טאב מסויים מתרנדר ואז להציג את ה-HTML הזה במקום קבוע. בצד-שרת, נקלוט את הבקשה הזו, ניקח את האלמנט Tab צד-שרת האחד הזה, נפעיל עליו RenderControl ונשלח בחזרה את ה-HTML ללקוח שיציג אותו בתוך <div>.