2008-11-08 65 views
4

我設置了一個用戶控制用XML配置驅動的內有條件的內容。通過示例來解釋更容易。看看下面的配置片斷:如何創建一個數據綁定直放站

<node> 
    <text lbl="Text:"/> 
    <checkbox lbl="Check me:" checked="true"/> 
</node> 

我正在努力實現到片斷轉換成一個單一的文本框和一個複選框控制。當然,如果代碼片段包含更多節點,則會自動生成更多控件。

給任務的迭代性,我選擇使用中繼器。在它內部,我放置了兩個(以及更多,參見波紋管)控件,一個CheckBox和一個Editbox。爲了選擇哪個控件被激活,我使用了一個內聯開關命令,檢查當前配置節點的名稱。

可悲的是,這是行不通的。問題在於,在數據綁定發生之後很長一段時間內,交換機正在運行。這本身不會是一個問題,並不是因爲配置節點可能提供所需的信息來綁定數據。考慮一下如果複選框控件試圖綁定到上面代碼片段中的文本節點,絕望地尋找它的「checked」屬性會發生什麼。

任何想法如何實現這一目標?

感謝, 波阿斯

這裏是我當前的代碼:

這裏是我的代碼(上面一個更復雜的語法比一個運行):

<asp:Repeater ID="settingRepeater" runat="server"> 
     <ItemTemplate> 
      <% 
       switch (((XmlNode)Page.GetDataItem()).LocalName) 
       { 
       case "text": 
      %> 
      <asp:Label ID="settingsLabel" CssClass="editlabel" Text='<%# XPath("@lbl") %>' runat="server" /> 
      <asp:TextBox ID="settingsLabelText" Text='<%# SettingsNode.SelectSingleNode(XPath("@xpath").ToString()).InnerText %>' 
       runat="server" AutoPostBack="true" Columns='<%# XmlUtils.OptReadInt((XmlNode)Page.GetDataItem(),"@width",20) %>' 
       /> 
      <% break; 
       case "checkbox": 
      %> 
      <asp:CheckBox ID="settingsCheckBox" Text='<%# XPath("@lbl") %>' runat="server" 
         Checked='<%# ((XmlElement)SettingsNode.SelectSingleNode(XPath("@xpath").ToString())).HasAttribute(XPath("@att").ToString()) %>' 
      /> 
      <% break; 
       } %> 
      &nbsp;&nbsp; 
     </ItemTemplate> 
    </asp:Repeater> 

回答

4

一個週末過去了,這裏是我想出了一個解決方案。我的主要目標是找到既能工作又能讓你在標記中指定項目模板的確切內容的東西。從代碼做事情會起作用,但仍然很麻煩。

代碼應該直接跟隨,但問題的要點在於兩部分。

第一種是使用Repeater項目創建的事件來過濾不需要的模板部分。

第二個是存儲在ViewState中做出的決定,以便在回發期間重新創建頁面。後面的內容至關重要,因爲您會注意到我使用了Item.DataItem。在回帖後,控制娛樂在頁面生命週期中發生得更早。當ItemCreate觸發時,DataItem爲空。

這裏是我的解決方案:

控制標記

<asp:Repeater ID="settingRepeater" runat="server" 
      onitemcreated="settingRepeater_ItemCreated" 
      > 
     <ItemTemplate> 
      <asp:PlaceHolder ID="text" runat="server"> 
        <asp:Label ID="settingsLabel" CssClass="editlabel" Text='<%# XPath("@lbl") %>' runat="server" /> 
        <asp:TextBox ID="settingsLabelText" runat="server" 
         Text='<%# SettingsNode.SelectSingleNode(XPath("@xpath").ToString()).InnerText %>' 
        Columns='<%# XmlUtils.OptReadInt((XmlNode)Page.GetDataItem(),"@width",20) %>' 

        /> 

      </asp:PlaceHolder> 
      <asp:PlaceHolder ID="att_adder" runat="server"> 
       <asp:CheckBox ID="settingsAttAdder" Text='<%# XPath("@lbl") %>' runat="server" 
          Checked='<%# ((XmlElement)SettingsNode.SelectSingleNode(XPath("@xpath").ToString())).HasAttribute(XPath("@att").ToString()) %>' 
       /> 
      </asp:PlaceHolder> 
     </ItemTemplate> 
    </asp:Repeater> 

注:額外的方便,我添加佔位符控制組的事情,讓這些控制刪除更容易的決定。

代碼背後

代碼波紋管是建立在概念,每一個轉發器產品的類型。該類型是從配置xml中提取的。在我的具體情況中,我可以通過ID將該類型轉換爲單個控件。如果需要,這可以很容易地修改。

protected List<string> repeaterItemTypes 
    { 
     get 
     { 
     List<string> ret = (List<string>)ViewState["repeaterItemTypes"]; 
     if (ret == null) 
     { 
      ret = new List<string>(); 
      ViewState["repeaterItemTypes"] = ret; 
     } 
     return ret; 
     } 
    } 

    protected void settingRepeater_ItemCreated(object sender, RepeaterItemEventArgs e) 
    { 
     string type; 
     if (e.Item.DataItem != null) 
     { 
     // data binding mode.. 
     type = ((XmlNode)e.Item.DataItem).LocalName; 
     int i = e.Item.ItemIndex; 
     if (i == repeaterItemTypes.Count) 
      repeaterItemTypes.Add(type); 
     else 
      repeaterItemTypes.Insert(e.Item.ItemIndex, type); 
     } 
     else 
     { 
     // restoring from ViewState 
     type = repeaterItemTypes[e.Item.ItemIndex]; 
     } 

     for (int i = e.Item.Controls.Count - 1; i >= 0; i--) 
     { 
     if (e.Item.Controls[i].ID != type) e.Item.Controls.RemoveAt(i); 
     } 
    } 
1

你需要的東西看起來更像這樣:

​​

然後全部您的控件在代碼隱藏中生成。