DCSIMG
Question from Tapuz .Net forum: Control Extenders in Microsoft AJAX Control toolkit with PagingBulletedList - Justin myJustin = new Justin( Expriences.Current );

Question from Tapuz .Net forum: Control Extenders in Microsoft AJAX Control toolkit with PagingBulletedList

שאלה:

אני צריך  להציג מידע ברשימה ממויינת אפלבתית.
בשביל זה בחרתי לעבוד עם PagingBulltedList של AJAX Control Toolkit.

איך אפשר לגרום לרשימה להציג את הסימן "#" שעל פיו יסנן את כל המספרים?

איך אפשר לקבל הודעה שהמשתמש בוחר אינדקס מסויים ולדעת איזה אינדקס נבחר?

 להדגמה חיה ניתן ללחוץ כאן - http://ajax.asp.net/ajaxtoolkit/PagingBulletedList/PagingBulletedList.aspx.

 

תשובה:

 השאלה הזו נוגעת לבדיוק כיצד ראוי לעבוד עם AJAX Control Toolkit כאשר צריך להרחיב אותו ולשנות את ההתנהגות הקיימת.

בואו נתחיל בלהכיר את ה-PagingBulletedList.
מדובר ב-AJAX Control Extender, כלומר זה פקד שמתלבש על פקד קיים.

במקרה שלנו ה-PagingBulletedList מתלבש על <asp:BulletedList> שזה פקד של ASP.Net 2.0 שמתרנדר לרשימה של <ul> ו-<li> ב-HTML. למשל, הפקד הבא:

    <asp:BulletedList ID="BulletedList1" runat="server" DisplayMode="Text">

                <asp:ListItem>writeln</asp:ListItem>

                <asp:ListItem>1566</asp:ListItem>

                <asp:ListItem>4556</asp:ListItem>

                <asp:ListItem>9556776</asp:ListItem>

                <asp:ListItem>12234</asp:ListItem>

                <asp:ListItem>1566</asp:ListItem>

                <asp:ListItem>abort</asp:ListItem>

                <asp:ListItem>add</asp:ListItem>

                <asp:ListItem>addBehavior</asp:ListItem>

                <asp:ListItem>AddChannel</asp:ListItem>

                <asp:ListItem>AddDesktopComponent</asp:ListItem>

                <asp:ListItem>addElement</asp:ListItem>

                <asp:ListItem>AddFavorite</asp:ListItem>

                <asp:ListItem>addImport</asp:ListItem>

                <asp:ListItem>addPageRule</asp:ListItem>

                <asp:ListItem>addReadRequest</asp:ListItem>

                <asp:ListItem>addRule</asp:ListItem>

                <asp:ListItem>AddSearchProvider</asp:ListItem>

                <asp:ListItem>alert</asp:ListItem>

                <asp:ListItem>appendChild</asp:ListItem>

                <asp:ListItem>appendData</asp:ListItem>

                <asp:ListItem>applyElement</asp:ListItem>

                <asp:ListItem>assign</asp:ListItem>

                <asp:ListItem>attachEvent</asp:ListItem>

                <asp:ListItem>AutoCompleteSaveForm</asp:ListItem>

         

                ...

            </asp:BulletedList>

יתרנדר לתצוגה הזו בצד לקוח בדפדפן:

image

עכשיו נרצה איכשהו למיין את הרשימה הקיימת הזו שלנו, שרק לפי האות הראשונה (או X אותיות ראשונות) נציג אותן ביחד.
כלומר, נוכל לראות ביחד רק את כל המילים שמתחילות ב-a, או כל המילים שמתחילות ב-b וכך הלאה.

בשביל מטרה זו יש את PagingBulltedList של AJAX Control Toolkit ש"מתלבש" על BulltedList רגיל ומאפשר דפדפוף בו לפי אינדקס.
למשל הפקד הבא:

            <ajaxToolkit:PagingBulletedListExtender runat="server"

                ID="PagingBulletedListExtender1"

                BehaviorID="PagingBulletedListBehavior1"

                TargetControlID="BulletedList1"

                ClientSort="true"

                IndexSize="1"

                Separator=" - " />

יגרום ל-BulltedList להיות מוצגת בצד לקוח כך: (לאחר שנלחץ על E)

image

 

 לחיצה על האות O למשל תגרום לסינון חדש:

image

 

 להדגמה חיה ניתן ללחוץ כאן - http://ajax.asp.net/ajaxtoolkit/PagingBulletedList/PagingBulletedList.aspx.

 

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

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

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

בואו נביט לתוך הקוד מקור של PagingBulltedList ונראה את זה.
נוריד מ-codeplex (אתר הפרוייקטים של מיקרוסופט) את הקוד העדכני - http://www.codeplex.com/AtlasControlToolkit/Release/ProjectReleases.aspx?ReleaseId=4923.
ובתוך התיקייה \AjaxControlToolkit\PagingBulletedList נוכל למצוא את קוד המקור מאחורי PagingBulletedList.

מאפיינים אמרנו שיש? בואו נראה אחד.

 AjaxControlToolkit.PagingBulletedListBehavior.prototype = {

 {

    ...

   this._heightValue = null;

 

    get_Height : function() {

        /// <value type="Number" integer="true">

        /// Height of the bulleted list

        /// </value>

        return this._heightValue;

    },

    set_Height : function(value) {

        if (this._heightValue != value) {

            this._heightValue = value;

            if (this.get_isInitialized()) {

                //Change Height in the DOM

                this._changeHeightDivContent();

            }

            this.raisePropertyChanged('Height');

        }

    },

    ...

}

תזכרו, כל זה Javascript.
אפשר לראות שיש שדה פנימי heightValue_, ויש שני מתודות שחושפות Getter ו-Setter למאפיין.
get_Height מחזיר את הגובה הנוכחי של האלמנט, ו-set_Height מעדכן את השדה הפנימי ודואג לשנות את הגובה בפועל של האלמנט.

אמרנו שיש קונסטרקטור?

AjaxControlToolkit.PagingBulletedListBehavior.prototype = {

    initialize : function() {

        /// <summary>

        /// Initialize the behavior

        /// </summary>

        AjaxControlToolkit.PagingBulletedListBehavior.callBaseMethod(this, 'initialize');

 

        // do alot of stuff

    },

    ...

}

אמרנו שיש אירועים?

    add_indexChanged : function(handler) {

        /// <summary>

        /// Add a handler to the indexChanged event

        /// </summary>

        /// <param name="handler" type="Function">

        /// Handler

        /// </param>

        this.get_events().addHandler('indexChanged', handler);

    },

    remove_indexChanged : function(handler) {

        /// <summary>

        /// Remove a handler from the indexChanged event

        /// </summary>

        /// <param name="handler" type="Function">

        /// Handler

        /// </param>

        this.get_events().removeHandler('indexChanged', handler);

    },

    raiseIndexChanged : function(eventArgs) {

        /// <summary>

        /// Raise the indexChanged event

        /// </summary>

        /// <param name="eventArgs" type="Sys.EventArgs">

        /// Event Arguments

        /// </param>

        var handler = this.get_events().getHandler('indexChanged');

        if (handler) {

            if (!eventArgs) {

                eventArgs = Sys.EventArgs.Empty;

            }

            handler(this, eventArgs);

        }

    },

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

עכשיו נראה איך מתממשקים למשל לאירוע של שינוי אינדקס.

בדף לדוגמה שמגיע עם Control Toolkit אפשר לראות את הקוד ג'אווה סקריפט:

    <script language="javascript" type="text/javascript">

        var bl;

 

        function pageLoad() {

            bl = $find('PagingBulletedListBehavior1');

        }

    </script>

זה הסינטקס להשיג את המופע צד לקוח של ה-PagingBulltedList שלנו לפי ID.

עכשיו נרצה לקבוע ולהדפיס למסך את הגובה של ה-Extender:

       function pageLoad() {

            bl = $find('PagingBulletedListBehavior1');

            bl.set_Height(250);

            alert(bl.get_Height());

            }

על המסך נראה:

image

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

עכשיו נירשם לאירוע שמדבר על שינוי אינדקס בלקוח.

        function onIndexchanged(sender, eventArgs)

        {

            alert(eventArgs.innerHTML + " " + eventArgs.tag);

        }

 

       function pageLoad() {

            bl = $find('PagingBulletedListBehavior1');

        // bl.set_Height(250);

        // alert(bl.get_Height());

            bl.add_indexChanged(onIndexchanged);

        }

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

image

קיבלנו שלחצנו על האות B באינדקס במקום 4 (היות ואנחנו סופרים מערך מ-0 אז B באמת נמצא במקום 4).

 

השאלה השנייה שקיבלנו היא איך ניתן לשנות את הסידור של ה-PagingBulltedList כך שיציג את הסימן "#" לכל קבוצת המספרים.

נפתח את קובץ הג'אווה סקריפט של PagingBulletedList ואחרי קריאה זריזה שלו נוכל למצוא שבאמצעות הוספה של השורה הבאה בשורה 258 בתוך המתודה _generateIndexAndTabForView נוכל לבצע את זה.

        if (index == "1" || index == "2" || index == "3" || index == "4" || index == "5" || index == "6" || index == "7" || index == "8" || index == "9" || index == "1" || index == "1")

       {

        index = "#";

       }

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

עכשיו השאלה היא איך נוסיף את השינוי הזה לפרוייקט שלנו.

אפשרות אחת היא לשנות את קובץ ה-JS של PagingBulletedListBehavior.js, לקמפל מחדש את Microsoft AJAX Control Toolkit ולהשתמש ב-DLL החדש שלנו.

אפשרות נוספת שהייתי רוצה להדגים היא שינוי בזמן ריצה של המתודה.

       function pageLoad() {

            bl = $find('PagingBulletedListBehavior1');

        // bl.set_Height(250);

        // alert(bl.get_Height());

        // bl.add_indexChanged(onIndexchanged);

            bl._generateIndexAndTabForView = function() {

            ...          

                if (index == "1" || index == "2" || index == "3" || index == "4" || index == "5" || index == "6" || index == "7" || index == "8" || index == "9" || index == "1" || index == "1")

                {

                    index = "#";

                }

            ...

            };

            bl._generateIndexAndTabForView();

        }

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

שנינו בזמן ריצה אצל את הלקוח את הפונקציה!

נראה את התוצאה של הקוד הזה:

image 

ובאמת בצד-לקוח קיבלנו קבוצה שמבוססת על הסימן # שמייצג את כל המספרים!

 

מתי נשנה בזמן ריצה ומתי נדאג לקמפל מחדש את ה-AJAX Control toolkit?

נתחיל בלדבר נגד שינוי בזמן ריצה של ה-AJAx Control Toolkit:
1. שינוי בזמן ריצה יוצר מצב שלא יודעים איזה קוד מריץ מה. כלומר, לא יודעים בכלל מול איזה מתודה רצים באותו רגע.
2. שינוי בזמן ריצה יוצר ערבוב של אחריות בין הפקד צד-לקוח לבין המחלקה שמשתמשת בה שבפועל קובעת מה המחלקה מריצה.
3. מדובר על דרך גרועה לבצע שינויים מאסיביים ב-toolkit.
4. היות ושנינו מתודה פרטית (אנו יודעים זאת כי המתודה ששנינו מתחילה עם קו תחתון _) יכול להיות שבגירסה הבאה היא בכלל לא תהיה קיימת והשינוי שלנו לא יעבוד אם נרצה לשדרג לגירסה הבאה של AJAX Control toolkit.

עכשיו נדבר בעד שינוי בזמן ריצה של ה-AJAX control toolkit:
1.  זה ממש מגניב. שנינו בזמן ריצה מתודה של מחלקה.
2. אם נשנה ישירות את הקובץ JS של ה-toolkit, נקמפל מחדש ונעבוד מול גירסה שלנו של ה-AJAX Control Toolkit כל שדרוג גירסה ל-AJAX Control Toolkit (שבערך פעם בחודש מתווספים לו פקדים) יגרור סט מאוד רציני של בדיקות ושינויים אצלנו. יש טכניקות שמאפשרות להתגבר על זה (לבצע Merge של הקבצים בגירסה הפרטית שלנו לתוך הגירסה הציבורית, אבל מדובר בתהליך ידני שיכול לקחת מספר שעות כל פעם).

 

קישור: http://www.tapuz.co.il/tapuzforum/main/Viewmsg.asp?forum=831&msgid=102202495

Published Wednesday, July 18, 2007 12:43 PM by Justin-Josef Angel [MVP]

Comments

No Comments