2017-05-26 50 views
0

我有以下SQL下拉列表中的GridView數據綁定行爲不正確ASP.NET C#

SELECT Equipment.* ,cast(EquipmentId as varchar(100)) + ' ' + EquipmentName as Name 
FROM Equipment 
WHERE Equipment.EquipmentCategoryID = @EquipmentCategoryID 
AND (Equipment.EquipmentSubCategoryID = @EquipmentSubCategoryID 
OR (@EquipmentSubCategoryID is null OR @EquipmentSubCategoryID = '')) 

在SQL Server如預期其行爲。當@EquipmentCategoryId是12並且@EquipmentSubCategoryID是空它將返回所有我想要的值。而當@EquipmentCategoryId是12並且@EquipmentSubCategoryID是另一個數字時,它返回的行數也是我想要的。

在它不表現爲預期的,返回的GridView每個dropdownlist所有行一個GridView的ASP.NET下拉列表,即使@EquipmentSubCategoryID有不同的數字,在SQL Server中的工作。 dropdownlist是這樣綁定的。

protected void ServiceFormsGV_RowDataBound(object sender, GridViewRowEventArgs e) 
{ 
    if (e.Row.RowType == DataControlRowType.DataRow) 
    {     
     HiddenField EquipmentCategoryIDHF = (HiddenField) e.Row.FindControl("EquipmentCategoryIDHF"); 
     HiddenField EquipmentSubCategoryIDHF = (HiddenField) e.Row.FindControl("EquipmentSubCategoryIDHF"); 
     DropDownList EquipmentDD = (DropDownList) e.Row.FindControl("EquipmentDD"); 
     EquipmentDS.SelectParameters["EquipmentCategoryID"].DefaultValue = EquipmentCategoryIDHF.Value;    
     EquipmentDS.SelectParameters["EquipmentSubCategoryID"].DefaultValue = EquipmentSubCategoryIDHF.Value; 
     EquipmentDD.Items.Clear(); 
     EquipmentDD.Items.Add(new ListItem()); 
     EquipmentDD.DataBind(); 
    } 
} 

我可以確認,通過該HiddenFields正在顯示正確的值,但ServiceFormsGVGridView方法每次在每個DropDownList所有行。 GridView如下。

<asp:GridView ID="ServiceFormsGV" runat="server" AutoGenerateColumns="False" DataKeyNames="ServiceFormID,EquipmentCategoryID1" DataSourceID="ServiceFormsDS" OnDataBound="ServiceFormsGV_DataBound" OnRowDataBound="ServiceFormsGV_RowDataBound"> 
<Columns> 
    <asp:TemplateField HeaderText="Machine Id"> 
      <ItemTemplate> 
       <asp:DropDownList ID="EquipmentDD" runat="server" AutoPostBack="True" DataSourceID="EquipmentDS" DataTextField="EquipmentName" AppendDataBoundItems="True" 
        DataValueField="EquipmentID" OnSelectedIndexChanged="EquipmentDD_SelectedIndexChanged"> 

而在我的SqlDataSource有

CancelSelectOnNullParameter="False" 

這是必要的。

我已經在配置數據源中測試了該查詢,它的行爲如預期。

Testing in ASP.NET SqlDataSource

+0

是否只有一個sqlDataSource用於所有下拉列表? –

+0

是的,我只使用1個sqlDataSource作爲下拉列表。雖然我在gridview中有其他下拉菜單,似乎在工作 –

+0

其他下拉菜單也會在gridview的每一行中加載不同的項目?你有沒有嘗試調試,看看是否正確的值傳遞給sqlDataSource? –

回答

1

此行爲背後的原因是SqlDataSource被用作GridView內下拉列表的數據源。

在DataGridView_RowDataBound事件期間,您將更改參數SqlDataSource的默認值並重新綁定該行的下拉列表。當您更改參數的默認值時,查詢執行結果SqlDataSource會影響所有下拉列表,因此最終所有下拉列表都將具有由gridview的最後一行傳遞的值生成的查詢結果。這就是爲什麼你在網格的所有下拉列表中得到相同的結果。

您需要每次運行查詢並檢索結果並將其分別綁定到每個下拉列表,而不使用它們之間的任何公共數據源。

儘管您找到的解決方案沒有問題,但需要打開SQL連接並針對DataGridView的每一行運行db查詢。

我建議的方法是從Equipment表中檢索所有行,並將它們存儲爲頁級別的實體集合,然後在rowDataBound事件過程中篩選當前類別和子類別的集合,並將篩選結果綁定到下拉列表。

以下是實體設備

public class Equipment 
{ 
    public int Id { get; set; } 

    public string Name { get; set; } 

    public string CategoryId { get; set; } 

    public string SubCategoryId { get; set; } 

    public string FullName 
    { 
     get 
     { 
      return string.Format("{0} {1}", Id, Name); 
     } 
    } 
} 

在Page_Load通過檢索數據庫中的所有設備,從表中的行填充設備的集合。

public partial class _Default : Page 
{ 
    private List<Equipment> equipments; 

    protected void Page_Load(object sender, EventArgs e) 
    { 
     equipments = new List<Equipment>(); 

     var commandText = "SELECT EquipmentId, EquipmentName, CategoryId, SubCategoryId FROM Equipment"; 

     using (var connection = new SqlConnection("Data Source=.;Initial Catalog=LocalDevDb;User id=sa;Password=Password1")) 
     { 
      using (var command = new SqlCommand(commandText, connection)) 
      { 
       command.CommandType = System.Data.CommandType.Text; 

       connection.Open(); 
       using (var reader = command.ExecuteReader(System.Data.CommandBehavior.CloseConnection)) 
       { 
        while (reader.Read()) 
        { 
         var equipment = new Equipment 
         { 
          Id = reader.GetInt32(0), 
          Name = reader.GetString(1), 
          CategoryId = reader.GetString(2), 
          SubCategoryId = reader.GetString(3), 
         }; 

         equipments.Add(equipment); 
        } 
       } 
      } 
     } 
    } 
} 

根據CategoryId和SubCategoryId過濾此集合並將結果綁定到DropDown。

protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e) 
{ 
    if (e.Row.RowType == DataControlRowType.DataRow) 
    { 
     DropDownList EquipmentDD = (DropDownList)e.Row.FindControl("dropDownList"); 

     HiddenField EquipmentCategoryIDHF = (HiddenField) e.Row.FindControl("EquipmentCategoryIDHF"); 
     HiddenField EquipmentSubCategoryIDHF = (HiddenField) e.Row.FindControl("EquipmentSubCategoryIDHF"); 

     var categoryId = EquipmentCategoryIDHF.Value; 
     var subCategoryId = EquipmentSubCategoryIDHF.Value; 

     Func<Equipment, bool> criteria; 

     if(!string.IsNullOrEmpty(subCategoryId)) 
     { 
      criteria = criteria = equip => equip.CategoryId == categoryId && equip.SubCategoryId == subCategoryId; 
     } 
     else 
     { 
      criteria = equip => equip.CategoryId == categoryId; 
     } 

     var list = equipments.Where(criteria).ToList(); 

     EquipmentDD.DataSource = list; 
     EquipmentDD.DataBind(); 
     EquipmentDD.Items.Insert(0, new ListItem()); 

    } 
} 

在我的示例中,CategoryId和SubCategoryId列是使用String數據類型創建的。如果它們不同於表格的列,則需要將它們更改爲適當的。

這應該可以幫助你解決你的問題。

+0

謝謝你的工作。 –

+0

雖然我的解決方案是正確的,解決了我的問題,但我相信您的解決方案更高效,這就是爲什麼我選擇了您的解決方案。 –

0

我已經找到了解決方案是SqlDataSource需求是在GridView該行。所以與ItemTemplate中的DropDownList在相同的地方。那就是在RowDataBound方法中爲每一行更新SqlDataSource。

protected void ServiceFormsGV_RowDataBound(object sender, GridViewRowEventArgs e) 
{ 
    if (e.Row.RowType == DataControlRowType.DataRow) 
    {     
     HiddenField EquipmentCategoryIDHF = (HiddenField) e.Row.FindControl("EquipmentCategoryIDHF"); 
     HiddenField EquipmentSubCategoryIDHF = (HiddenField) e.Row.FindControl("EquipmentSubCategoryIDHF"); 
     SqlDataSource EquipmentDS = (SqlDataSource)e.Row.FindControl("EquipmentDS"); 
     DropDownList EquipmentDD = (DropDownList) e.Row.FindControl("EquipmentDD"); 
     EquipmentDS.SelectParameters["EquipmentCategoryID"].DefaultValue = EquipmentCategoryIDHF.Value;    
     EquipmentDS.SelectParameters["EquipmentSubCategoryID"].DefaultValue = EquipmentSubCategoryIDHF.Value; 
     EquipmentDD.Items.Clear(); 
     EquipmentDD.Items.Add(new ListItem()); 
     EquipmentDD.DataBind(); 
    } 
} 

<asp:GridView ID="ServiceFormsGV" runat="server" AutoGenerateColumns="False" DataKeyNames="ServiceFormID,EquipmentCategoryID1" DataSourceID="ServiceFormsDS" OnDataBound="ServiceFormsGV_DataBound" OnRowDataBound="ServiceFormsGV_RowDataBound"> 
    <Columns> 
     <asp:TemplateField HeaderText="Machine Id"> 
      <ItemTemplate> 
       <asp:DropDownList ID="EquipmentDD" runat="server" AutoPostBack="True" DataSourceID="EquipmentDS" 
        DataTextField="EquipmentName" AppendDataBoundItems="True" 
         DataValueField="EquipmentID" OnSelectedIndexChanged="EquipmentDD_SelectedIndexChanged"> 
       <asp:SqlDataSource ID="EquipmentDS" runat="server" CancelSelectOnNullParameter="False" ConnectionString="<%$ ConnectionStrings:XXXXXXXXXXXXXXXXX %>" SelectCommand="SELECT Equipment.* ,cast(EquipmentId as varchar(100)) + ' ' + EquipmentName as Name FROM Equipment WHERE Equipment.EquipmentCategoryID = @EquipmentCategoryID AND (Equipment.EquipmentSubCategoryID = @EquipmentSubCategoryID OR (@EquipmentSubCategoryID is null OR @EquipmentSubCategoryID = ''))"> 
        <SelectParameters> 
         <asp:Parameter Name="EquipmentCategoryID" /> 
         <asp:Parameter Name="EquipmentSubCategoryID" /> 
        </SelectParameters> 
       </asp:SqlDataSource> 
      </ItemTemplate> 

它是有道理的,它的工作原理。

+1

我正在準備一個解決方案,但你首先發現它。 :)。這也是一個解決方案。如果您不想爲GridView的每一行打開連接和查詢數據庫,則可以考慮檢索page_load中的所有設備,並創建一個列表並在rowDataBound事件中過濾該列表。讓我知道你是否希望我提供該解決方案。 –

+0

是的,我想看看這個解決方案。謝謝。 –

+0

我剛剛發佈瞭解決方案。 –