Καλώς ορίσατε στο dotNETZone.gr - Σύνδεση | Εγγραφή | Βοήθεια
σε

 

Αρχική σελίδα Ιστολόγια Συζητήσεις Εκθέσεις Φωτογραφιών Αρχειοθήκες

Δυναμικά templates σε DataList

Îåêßíçóå áðü ôï ìÝëïò Νατάσα Μανουσοπούλου. Τελευταία δημοσίευση από το μέλος Νατάσα Μανουσοπούλου στις 02-02-2006, 09:45. Υπάρχουν 3 απαντήσεις.
Ταξινόμηση Δημοσιεύσεων: Προηγούμενο Επόμενο
  •  01-02-2006, 18:03 9118

    Δυναμικά templates σε DataList

    Έχω ένα DataList στο οποίο θέτω προγραμματιστικά τα ItemTemplate, HeaderTemplate, FooterTemplate με την Page.LoadTemplate. Τα user controls που έχω σαν templates είναι της μορφής



    <%@ Language="c#" %>
    <asp:Table runat="server" id="Table2365">
    <asp:TableRow>
    </asp:TableRow>
    </asp:Table>

    To DataList έχει ExtractTemplateRows=true. Όμως τελικά παίρνω exception: A Table control was not found in the template for 'allCategories' for an item of type 'ListItemType.Header'.

    Δοκίμασα να κάνω το LoadTemplate σε όλα τα πιθανά σημεία του κύκλου ζωής της σελίδας, χωρίς αποτέλεσμα. Καμία ιδέα;

     


    Νατάσα Μανουσοπούλου
  •  01-02-2006, 18:48 9119 σε απάντηση της 9118

    Απ: Δυναμικά templates σε DataList

    Δείξε λίγο κώδικα παραπάνω, πως βάζεις το controls μέσα και πως τα ψάχνεις μετά...
    Χρήστος Γεωργακόπουλος
  •  02-02-2006, 09:13 9139 σε απάντηση της 9119

    Απ: Δυναμικά templates σε DataList

    Έχω λοιπόν ένα generic user control που περιέχει ένα data list στο οποίο θέλω να δείξω ένα τυχόν DataTable χτίζοντας τις κολώνες στο runtime με ένα συγκεκριμένο τρόπο (ο οποίος έχει προδιαγραφές για το πώς θα είναι το Item, το EditItem, το Header και το Footer). To DataList είναι κάπως έτσι:



    <asp:DataList id="allData" runat="server" Width="100%" GridLines="None" ShowHeader="True"
     BorderStyle="None" BorderWidth="0px" CellPadding="2" ShowFooter="True" ExtractTemplateRows="True">

    ... (item styles μόνο)
    </asp:DataList>

    Και στην OnLoad του user control, καλείται κώδικας που κάνει το παρακάτω:



       a_List.ExtractTemplateRows = true;

       string strTemplateName = "~/Templates/" + a_Data.TableName + "Item.ascx";
       CreateTemplate(a_Data, strTemplateName, TemplateType.Item);
       a_List.ItemTemplate = Page.LoadTemplate(strTemplateName);

    Η CreateTemplate γεννά με βάση τις στήλες του a_Data (DataTable) ένα user control σαν κι αυτό:



    <%@ Language="c#" %>
    <asp:Table runat="server">
    <asp:TableRow>
    <asp:TableCell><%# DataBinder.Eval(((DataListItem)Container).DataItem, "ID") %></asp:TableCell>
    <asp:TableCell><%# DataBinder.Eval(((DataListItem)Container).DataItem, "Description") %></asp:TableCell>
    </asp:TableRow>
    </asp:Table>

    και τα αντίστοιχα για τα άλλα templates, τα οποία επίσης ανατίθενται στο DataList.

    Πάνω στο rendering του control όμως παίρνω το exception που ανέφερα.

    Όσο και να έψαξα, βρήκα μόνο μια ερώτηση από έναν άλλο ταλαίπωρο που ρώταγε το ίδιο πράγμα και κανείς δεν του είχε απαντήσει. Ελπίζω ότι θα είμαι πιο τυχερή...

     


    Νατάσα Μανουσοπούλου
  •  02-02-2006, 09:45 9141 σε απάντηση της 9139

    Απ: Δυναμικά templates σε DataList

    Σήμερα το πρωί, με πιο καθαρό μυαλό, βρήκα τι συμβαίνει, με τη βοήθεια του θεϊκού Reflector και πρέπει να το μοιραστώ οπωσδήποτε μαζί σας.

    Ο κώδικας της DataListItem.RenderItemInternal (από τον οποίο έπαιρνα το exception) είναι ο παρακάτω:



    private void RenderItemInternal(HtmlTextWriter writer, bool extractRows, bool tableLayout)
    {
          if (!extractRows)
          {
                if (tableLayout)
                {
                      this.RenderContents(writer);
                }
                else
                {
                      base.RenderControl(writer);
                }
          }
          else
          {
                IEnumerator enumerator1 = this.Controls.GetEnumerator();
                Table table1 = null;
                bool flag1 = false;
                while (enumerator1.MoveNext())
                {
                      flag1 = true;
                      Control control1 = (Control) enumerator1.Current;
                      if (control1 is Table)
                      {
                            table1 = (Table) control1;
                            break;
                      }
                }
                if (table1 != null)
                {
                      IEnumerator enumerator2 = table1.Rows.GetEnumerator();
                      while (enumerator2.MoveNext())
                      {
                            TableRow row1 = (TableRow) enumerator2.Current;
                            row1.RenderControl(writer);
                      }
                }
                else if (flag1)
                {
                      throw new HttpException(HttpRuntime.FormatResourceString("DataList_TemplateTableNotFound", this.Parent.ID, this.itemType.ToString()));
                }
          }
    }

    Όπως φαίνεται λοιπόν εδώ, όταν το ExtractTemplateRows=true, το DataListItem ελέγχει τα controls του για να βρει ένα Table control και να πάρει τις γραμμές του. Όμως, όταν το ItemTemplate έχει φορτωθεί από user control, τότε το DataListItem έχει ένα child control μόνο το οποίο είναι τύπου MyUserControl_ascx και βέβαια δεν είναι Table (αλλά το περιέχει). Οπότε Table δε βρίσκει, και ρίχνει το exception.

    Ποιο ήταν το workaround που έκανα με βάση αυτό; Στην OnPreRender, εφόσον το DataListItem περιέχει κάποιο user control (το οποίο έχει φορτωθεί από template) και το ExtractTemplateRows=true, κάνω reparent τα child controls του user control στο DataListItem, οπότε βρίσκει τον πίνακα. Αυτό βέβαια είναι εφικτό δεδομένου ότι το user control δεν έχει καθόλου κώδικα από πίσω, οπότε μπορεί να εξαφανιστεί χωρίς συνέπειες.

    Big Smile [:D]


    Νατάσα Μανουσοπούλου
Προβολή Τροφοδοσίας RSS με μορφή XML
Με χρήση του Community Server (Commercial Edition), από την Telligent Systems