2012-08-28 42 views
1

我有一個FormView用於查看,編輯和插入項目到MSSQL數據庫。 FormView連接到一個LinqDataSource,我使用它的Selecting事件過濾基於查詢字符串中傳遞的參數(列)在FormView中顯示的數據。保存FormView的過濾結果時,DropDownList值爲空

在FormView中,我有一個DropDownList來顯示相關表中的值。除了當我嘗試編輯時,所有東西都可以正常工作 - 出於某種原因,當我嘗試保存編輯時(即使選擇了某個值),DropDownList的選定值始終爲空。插入工作,因爲它應該。

我已經將問題追溯到我做過濾的Selecting事件。如果我註釋掉進行過濾的方法,它會成功更新項目 - 但我無法弄清楚爲什麼過濾正在破壞更新。

這裏是我的(縮短)FormView控件:

<asp:FormView ID="fvData" runat="server" AllowPaging="True" 
    DataKeyNames="ID" DataSourceID="ldsData" 
    ondatabound="fvData_DataBound"> 
    <EditItemTemplate> 
     <table class="pad5"> 
      <tr> 
       <td class="field-name">AREA:</td> 
       <td><asp:DropDownList ID="cboAREA" runat="server" DataTextField="AREA_NAME" DataValueField="AREA1" SelectedValue='<%# Bind("AREA") %>' DataSourceID="ldsAreas" /></td> 
      </tr> 
      <tr> 
       <td class="field-name">LOOP:</td> 
       <td><asp:TextBox ID="txtLOOP" runat="server" Text='<%# Bind("LOOP") %>' /></td> 
      </tr> 
      <tr> 
       <td class="field-name">LOOP DESCRIPTION:</td> 
       <td><asp:TextBox ID="txtLOOP_DESCRIPTION" runat="server" 
      Text='<%# Bind("LOOP_DESCRIPTION") %>' style="width: 600px" /></td> 
      </tr> 
     </table> 

     <asp:Button ID="btnUpdate" runat="server" Text="Update" CommandName="Update" CausesValidation="True" /> 
     <asp:Button ID="btnCancel" runat="server" Text="Cancel" CommandName="Cancel" CausesValidation="False" /> 
    </EditItemTemplate> 
    <InsertItemTemplate> 
     <table class="pad5"> 
      <tr> 
       <td class="field-name">AREA:</td> 
       <td> 
        <asp:DropDownList ID="cboAREA" runat="server" DataTextField="AREA_NAME" 
         DataValueField="AREA1" SelectedValue='<%# Bind("AREA") %>' AppendDataBoundItems="true" DataSourceID="ldsAreas"> 
          <asp:ListItem Text="" Value="" /> 
         </asp:DropDownList> 
       </td> 
      </tr> 
      <tr> 
       <td class="field-name">LOOP:</td> 
       <td><asp:TextBox ID="txtLOOP" runat="server" Text='<%# Bind("LOOP") %>' /></td> 
      </tr> 
      <tr> 
       <td class="field-name">LOOP DESCRIPTION:</td> 
       <td><asp:TextBox ID="txtLOOP_DESCRIPTION" runat="server" 
      Text='<%# Bind("LOOP_DESCRIPTION") %>' style="width: 600px" /></td> 
      </tr> 
     </table> 

     <asp:Button ID="btnInsert" runat="server" Text="Insert" CommandName="Insert" CausesValidation="True" /> 
     <asp:Button ID="btnCancel" runat="server" Text="Cancel" CommandName="Cancel" CausesValidation="False" /> 
    </InsertItemTemplate> 
</asp:FormView> 

的使用LinqDataSource:

<asp:LinqDataSource ID="ldsData" runat="server" 
    ContextTypeName="E_and_I.EAndIDataDataContext" EnableDelete="True" 
    EnableInsert="True" EnableUpdate="True" EntityTypeName="" 
    TableName="INSTRUMENT_LOOP_DESCRIPTIONs" onselecting="ldsData_Selecting" OrderBy="ID ASC" > 
</asp:LinqDataSource> 

ldsData_Selecting方法:

protected void ldsData_Selecting(object sender, LinqDataSourceSelectEventArgs e) 
{ 
    EI.FilterData<INSTRUMENT_LOOP_DESCRIPTION>(ref e, db.INSTRUMENT_LOOP_DESCRIPTIONs, this.db); 
} 

最後EI.FilterData

public static void FilterData<T>(ref LinqDataSourceSelectEventArgs e, IEnumerable<T> source, EAndIDataDataContext db) 
{ 
    if (HttpContext.Current.Request.QueryString.Keys.Count > 0) 
    { 
     var result = source.AsQueryable(); 
     bool filtered = false; 

     // get column names 
     var columnNames = db.Mapping.MappingSource.GetModel(typeof(EAndIDataDataContext)).GetMetaType(typeof(T)).DataMembers; 

     foreach (string key in HttpContext.Current.Request.QueryString.Keys) 
     { 
      string val = HttpContext.Current.Request.QueryString[key]; 

      // check the query string key exists as a column in the table, etc 
      if (columnNames.SingleOrDefault(c => c.Name == key) != null && val.Trim() != "" && val != "*") 
      { 
       result = result.WhereLike(key, val.Replace("?", "_").Replace("*", "%")); 
       filtered = true; 
      } 
     } 

     if (filtered) 
      e.Result = result; 
    } 
} 

是否有任何理由篩選結果會破壞更新(並且只有DropDownList的 - 文本框工作正常)?過濾完美地工作(也就是說,FormView只顯示用戶輸入的記錄參數);如果你想知道WhereLike擴展方法的作用,你可以查看this question's的答案。

+0

嘗試在ldsData_Selecting處理程序中編寫過濾器代碼並查看會發生什麼情況?我認爲''錯誤*'ondatabound =「fvData_DataBound」' – adatapost

+0

過濾器代碼只在'ldsData_Selecting'事件中執行,而不是在'fvData_DataBound'中執行。如果它處於ReadOnly模式,'fvData_DataBound'事件只是在FormView中設置一個標籤。 – Hoff

回答

0

因爲當您通過編輯發佈數據時,您將綁定數據,因此您將刪除所選的值。

解決方法:調整你的綁定

If(! IsPostBack) 
{ 
    //Here realize your bind of data 

} 

爲了堅持你的DATAS,使用ViewState的

有了這個解決方案當你發佈你不要再綁定數據,所以ViewState中包含您選擇的值

+0

如果是這種情況,爲什麼插入工作?另外,我試過使用if(!Page.IsPostBack)',但是這個過濾只能在第一頁加載時使用。當您在FormView中切換模式時,由於PostBack,過濾不再起作用。 – Hoff

+0

插入工作是正常的,因爲你每次綁定你的數據Hoff,但是當你選擇控制數據的時候,這個數據會保存在視圖狀態,當你重新綁定你時擦除 –

+0

你試試! IsPostBack,但是這次你在你的控件上設置EnableViewState =「true」 –

0

您的兩種情況下拉列表有所不同,我認爲這可能是造成這種情況的原因。對於插入,您有AppendDataBoundItems =「true」,而對於上面的更新表單,此標誌未設置(並且默認爲false)。就提交表單而言,這意味着對於插入表單,當它重新綁定時,它會將這些項目追加到當前列表中而不是清除它們;但對於更新表單,因爲它沒有設置爲追加,所以它會清除這些項目,然後綁定它們 - 所以綁定在兩種情況下都會發生,但在更新表單的情況下,它會在發生時清除項目,並且給你空白的數據。

而不是僅拒絕回發過濾,這會導致您的表單最終失敗,而是根據導致回發的控件進行過濾。在該函數的頂部,您可以捕獲導致回發的控件ID,然後只有當它不是來自觸發數據存儲步驟的按鈕的回發時才能過濾。如果這樣的話,我相信你應該能夠完全消除AppendDataBoundItems標誌。

我的意思的代碼段更新:

string initControl = Request.Form["__EVENTTARGET"]; 
if (!IsPostBack || (initControl != "btnInsert" && initControl != "btnUpdate") { 
    // code here 
} 

這樣做是擴大回發的檢查,這樣的條件是允許無論是如果沒有一個回(你以前測試),但看房,只要控件回發不是觸發依賴於這些綁定元素內容的事件的控件,它也將允許列表更新,如果表單被回發。這應該意味着您可以避免僅在第一次加載頁面時出現問題。

此外,如果您需要控制綁定不管,您可以添加一個全局布爾變量的腳本;如果不符合上述條件(即,如果阻止綁定),則將其設置爲False,然後將其設置爲True。然後,您可以檢查Page_PreRender函數中的布爾值,如果它設置爲true,則可以在該步驟執行控件的後期綁定(只有在插入/更新事件已經處理後纔會觸發,所以綁定在該點將不再影響表單處理的結果)。

+0

過濾是基於查詢字符串而不是控制。 .. – Hoff

+0

在事件ldsData_Selecting中,在函數被調用來檢查查詢字符串之前,您應該能夠檢查並查看是否a)它是回發,如前面的回覆建議,以及b)如果是,什麼控制引發了回傳。 (這裏的基礎知識在檢查Request.Form [「__ EVENTTARGET」] - 有一些弱點,但這是關鍵。) –

+0

除此之外 - 只是發佈上面的代碼片段。 –