【问题标题】:Double Databinding Cascading DropDownList to two SqlDataSources in a FormView双重数据绑定级联下拉列表到 FormView 中的两个 SqlDataSource
【发布时间】:2012-02-07 18:50:23
【问题描述】:

我有两个级联下拉列表,我试图分别绑定到两个单独的 SqlDataSource。

这些下拉列表存在于 FormView 的 EditItemTemplate 中。在 EditItemTemplate 内部存在两个填充部门和作业名的 sqldatasource 控件。 DeptID 和 JobID 是这些表中的主键。这在部门和工作之间产生了“级联效应”。选择部门后,仅显示与该部门关联的职位。

这块工作正常。

<asp:FormView ID="frmProfile" runat="server" DataSourceID="sqlDSProfile" 
    DataKeyNames="EUID" style="margin-top: 0px">
    <EditItemTemplate>
        <asp:DropDownList ID="ddlDepartments" runat="server" Width="135px"
            DataSourceID="sqlDSDepartments" 
            DataTextField="Department" 
            DataValueField="DeptID" AutoPostBack="True" 
            SelectedValue='<%# Bind("CurrentDeptID") %>' 
            AppendDataBoundItems="true" >
                <asp:ListItem></asp:ListItem>
        </asp:DropDownList>

        <asp:DropDownList ID="ddlJobNames" runat="server" Width="185px"
            DataSourceID="sqlDSJobs" DataTextField="JobName" DataValueField="JobID" 
            SelectedValue='<%# Bind("CurrentJobID") %>' 
            AppendDataBoundItems="true" >
                <asp:ListItem></asp:ListItem>
        </asp:DropDownList>

        <asp:SqlDataSource ID="sqlDSDepartments" runat="server" 
            ConnectionString="<%$ ConnectionStrings:JobsDB %>" 
            SelectCommand="SELECT tblDepartments.DeptID, 
                                  tblDepartments.Department 
                           FROM tblDepartments" />

        <asp:SqlDataSource ID="sqlDSJobs" runat="server" 
            ConnectionString="<%$ ConnectionStrings:JobsDB %>" 
            SelectCommand="SELECT tblJobs.JobID, tblJobs.JobName FROM tblJobs
                           INNER JOIN tblDeptsJobs ON tblDeptsJobs.JobID = tblJobs.JobID
                           WHERE tblDeptsJobs.DeptID = @DeptID" >
            <SelectParameters>
                <asp:ControlParameter ControlID="ddlDepartments" Name="DeptID" 
                    PropertyName="SelectedValue" />
            </SelectParameters>
        </asp:SqlDataSource>
    </EditItemTemplate>
</asp:FormView>

在表单视图之外存在 SqlDataSource,它将所有信息绑定到更新语句中的 Employee 表。我将在此 SqlDataSource 中保留所有其他信息,即使它已从上面的 FormView 中省略。

<asp:SqlDataSource ID="sqlDSProfile" runat="server" 
    ConnectionString="<%$ ConnectionStrings:JobsDB %>" 
    SelectCommand="SELECT tblEmployee.EUID, 
                tblEmployee.DateHired, 
                tblEmployee.LastName, 
                tblEmployee.HiredLastName, 
                tblEmployee.FirstName, 
                tblEmployee.Role, 
                tblEmployee.JobGrade, 
                tblEmployee.CurrentDeptID, 
                tblDepartments.Department, 
                tblDepartments.DeptID, 
                tblEmployee.CurrentJobID, 
                tblJobs.JobName, 
                tblJobs.JobID, 
                tblEmployee.CurrentShift, 
                tblEmployee.JobDate, 
                tblEmployee.IsDisplaced, 
                tblEmployee.EligibilityDate 
            FROM tblEmployee 
                LEFT OUTER JOIN tblDepartments ON tblEmployee.CurrentDeptID = tblDepartments.DeptID 
                EFT OUTER JOIN tblJobs ON tblEmployee.CurrentJobID = tblJobs.JobID 
            WHERE (tblEmployee.EUID = @EUID)"
    UpdateCommand="UPDATE [tblEmployee] 
                SET [tblEmployee].[DateHired] = @DateHired, 
                    [tblEmployee].[LastName] = @LastName, 
                    [tblEmployee].[HiredLastName] = @HiredLastName, 
                    [tblEmployee].[FirstName] = @FirstName, 
                    [tblEmployee].[Role] = @Role, 
                    [tblEmployee].[JobGrade] = @JobGrade, 
                    [tblEmployee].[CurrentDeptID] = @CurrentDeptID, 
                    [tblEmployee].[CurrentJobID] = @CurrentJobID, 
                    [tblEmployee].[CurrentShift] = @CurrentShift, 
                    [tblEmployee].[JobDate] = @JobDate, 
                    [tblEmployee].[IsDisplaced] = @IsDisplaced, 
                    [tblEmployee].[EligibilityDate] = @EligibilityDate 
                WHERE [tblEmployee].[EUID] = @EUID"
                    ProviderName="System.Data.SqlClient">
    <SelectParameters>
        <asp:SessionParameter Name="EUID" SessionField="sProfileEUID" DbType="String" />
    </SelectParameters>
    <UpdateParameters>
        <asp:Parameter Name="DateHired" DbType="Date" />
        <asp:Parameter Name="LastName" DbType="String" />
        <asp:Parameter Name="HiredLastName" DbType="String" />
        <asp:Parameter Name="FirstName" DbType="String" />
        <asp:Parameter Name="Role" DbType="String" />
        <asp:Parameter Name="JobGrade" DbType="Byte" />
        <asp:Parameter Name="CurrentDeptID" DbType="Int32" />
        <asp:Parameter Name="CurrentJobID" DbType="Int32" />
        <asp:Parameter Name="CurrentShift" DbType="Int32" />
        <asp:Parameter Name="JobDate" DbType="Date" />
        <asp:Parameter Name="IsDisplaced" DbType="Boolean"/>
        <asp:Parameter Name="EligibilityDate" DbType="Date"/>
        <asp:SessionParameter Name="EUID" SessionField="sProfileEUID" DbType="String" />
    </UpdateParameters>
</asp:SqlDataSource>

我不知道如何绑定的唯一部分是部门和工作。其他一切都在工作。我尝试在 DropDownList 控件中使用以下代码...

SelectedValue='<%# Bind("CurrentDeptID") %>'
SelectedValue='<%# Bind("CurrentJobID") %>'

...但是这些会导致错误。

总结

当用户单击编辑时,我需要两个下拉框中的值从主 sqlDSProfile 数据源中提取它们的选定值,但我需要它们是可更新的。我已经达到了可以更新和绑定员工所属工作的地步,但是由于下拉列表级联,当我尝试更改部门时,AutoPostBack 会破坏 sqlDSProfile - CurrentJobID 和 ddlJobs 之间的绑定。

更新

我在 select 语句中添加了 tblEmployee.CurrentDeptIDtblEmployee.CurrentJobID,并在 DropDownList 控件中添加了 Bind() 语句。

SelectedValue='<%# Bind("CurrentDeptID") %>' 
SelectedValue='<%# Bind("CurrentJobID") %>' 

这两个 DropDownLists 现在填充了从 Employee 表中提取的准确信息,显示了员工所属的部门和工作。

这两个 DropDownLists 也由 FormView 内的两个 SqlDataSources 填充,为我提供了更改部门和更改工作的选项。

当我更改工作时,它会起作用并且员工的工作也会更新。

当我更改部门时,它会中断说DataBinding methods such as Eval(), XPath(), and Bind() can only be used in the context of a databound control.

即将完成

我从 ddlJobs 中删除了数据绑定,并在后台对其进行了编码。

Protected Sub frmProfile_ItemUpdating(sender As Object, e As System.Web.UI.WebControls.FormViewUpdateEventArgs) Handles frmProfile.ItemUpdating
    If frmProfile.CurrentMode = FormViewMode.Edit Then
        e.NewValues("CurrentJobID") = DirectCast(DirectCast(sender, FormView).FindControl("ddlJobs"), DropDownList).SelectedValue
    End If
End Sub

剩下的唯一部分是构建 ddlDepartments 更改时的代码。

伪代码...

    ' If Item exists in ddlJobs Then
    '   select item (CurrentJobID)
    ' else
    '   select index 0 and make them pick something new
    ' end if

如此接近!

再次更新

这是我为松散绑定而开发的代码。在 page_load 中,我试图从 sqlDSProfile 中提取 CurrentJobID 的内容,并检查该值是否存在于 ddlJobs 中。如果是,我想将 ddlJobs.SelectedValue = 设置为该 CurrentJobID。如果不是,我想将 selectedindex 设置为 0,这是一条说“选择一个”或其他内容的消息。

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

    If frmProfile.CurrentMode = FormViewMode.Edit Then

        ' Need to determine if the CurrentJobID returned in the select statement
        ' exists in the ddlJobs dropdownlist.  If it does, set that to the
        ' selectedvalue, if not set it to 0 so the user can select a new job.

        Dim ddlJobs As DropDownList = frmProfile.FindControl("ddlJobs")
        Dim dvProfile As DataView = sqlDSProfile.Select(DataSourceSelectArguments.Empty)
        Dim drvProfile As DataRowView = dvProfile(0)

        If ddlJobs.Items.FindByValue(drvProfile("CurrentJobID")) Is DBNull.Value Then
            ddlJobs.SelectedIndex = 0
        Else
            ddlJobs.SelectedValue = drvProfile("CurrentJobID")
        End If

    End If

End Sub

它在我检查 dbnull.value 的行上返回一个空引用异常

【问题讨论】:

    标签: asp.net vb.net tsql .net-4.0 2-way-object-databinding


    【解决方案1】:

    我遇到了类似的问题,并找到了一个非常简单的解决方案(并且在 c# 中)。想象一个带有表 Questions 的数据库,与类别和子类别表相关(它们也是相关的和受约束的)。当尝试更新现有记录时,asp 会引发错误。这是我根据 Lucretius 等人提供的上述信息制定的解决方案。

    1. 仅对父下拉列表进行数据绑定
    2. 想办法在数据源的更新事件中插入子下拉选择值。

    作为:

     protected void odseditquestion_Updating(object sender, ObjectDataSourceMethodEventArgs e)
        {
            //dynamically assign value from ddlsubcategory to odseditquestion on updating event
            //you really should not have to do this
            DropDownList ddlsubcategory = (DropDownList)fveditquestion.FindControl("ddlsubcategory");
            e.InputParameters["subcatid"] = (ddlsubcategory.SelectedValue);
        }
    

    它适用于我的应用程序。希望对大家有所帮助,这个花了我半天时间,比如asp!!

    【讨论】:

      【解决方案2】:

      问题可能是更新语句中SqlDSProfile 中的tlbEmployee 列与控件使用的字段名称不匹配。您遵循的其他程序是正确的。

      SqlDataSource control expects field names it updates to be similar with those bound to the controls(fields) inside the DataBound control.

      解决方案可以是:将所有更新 Parameters 更改为 ControlParameters,并为每个更新引用正确的控件

      更新:等等,我认为问题在于您的 SqlDSProfile 的 select 语句应该包含:CurrentDeptIDCurrentJobID。试试看:

      <asp:SqlDataSource ID="sqlDSProfile" runat="server" 
      ConnectionString="<%$ ConnectionStrings:JobsDB %>" 
      SelectCommand="SELECT tblEmployee.EUID, 
                  tblEmployee.DateHired, 
                  tblEmployee.LastName, 
                  tblEmployee.HiredLastName, 
                  tblEmployee.FirstName, 
                  tblEmployee.Role, 
                  tblEmployee.JobGrade, 
                  tblDepartments.Department, 
                  tblJobs.JobName, 
                  tblEmployee.CurrentShift, 
                  tblEmployee.JobDate, 
                  tblEmployee.IsDisplaced, 
                  tblEmployee.EligibilityDate 
                  tblEmployee.CurrentDeptID, 
                  tblEmployee.CurrentJobID 
              FROM tblEmployee 
      

      建议:逐部分测试您的代码。
      试试不带下拉列表的代码,单独测试
      添加一个下拉列表
      在选择查询中使用 select * from ...
      测试时避免使用 ajax
      如果你做到了
      在部分之后添加部分代码部分
      最后使用部分更新(ajax)

      【讨论】:

      • 我认为你在正确的轨道上,但有一些问题。将Parameter 更改为ControlParameter 会产生现在必须从SqlDataSource 对象的FormView 外部引用FormView 中的子项的问题。我在 Select 语句中添加了值,您是说参数名称需要在每个 SqlDataSource 之间匹配...比如将 CurrentDeptID 更改为 DeptID?
      • 不,我的意思是 SqlDataSource SqlDSProfile(提供数据并收集回编辑过的数据的那个)应该能够收集回数据,但是当它收集 Bind()方法应包含与数据源中的字段匹配的字段。而且由于 Bind() 是一种双向方法,因此该字段也应该在 select 语句和 Update 语句中,试试我的更新
      • 当我改变部门时,它想改变我想要它做的工作列表,但是因为它绑定到什么 tblEmployee.CurrntJobID 它打破了?
      • StackOverflow 有大小限制,我已将其发布到博客上。 sysadminfactotum.blogspot.com/2012/02/…我正在为你清理源码。
      • 我没有看到大问题,除了查询和控件的复制粘贴错位。看看我的更新
      【解决方案3】:

      我现在有了一个可行的解决方案,部分归功于 Nuux 和一堆在线研究。关于 join 语句的提示不相关,但是关于在我的选择查询中包含“CurrentJobID”和“CurrentDeptID”的提示是正确的。

      除此之外,我还必须对控件进行一些修改。两个级联下拉列表如下。 ddlJobs 下拉列表的行为类似于普通的数据绑定控件,但它没有我在原始帖子中尝试的 Bind("CurrentJobID") 语句。

      <asp:DropDownList ID="ddlDepartments" runat="server" Width="185px" 
          DataSourceID="sqlDSDepartments" 
          DataTextField="Department" 
          DataValueField="DeptID" 
          SelectedValue='<%# Bind("CurrentDeptID") %>' 
          AppendDataBoundItems="true" 
          AutoPostBack="True" >
              <asp:ListItem Text="--Select One--" Value="" />                                                
      </asp:DropDownList>
      
      <asp:DropDownList ID="ddlJobs" runat="server" Width="185px"
          DataSourceID="sqlDSJobs" 
          DataTextField="JobName" 
          DataValueField="JobID" 
          AppendDataBoundItems="true" 
          OnDataBinding="ddlJobs_DataBinding" />
      

      自定义例程“ddlJobs_DataBinding”唯一要做的就是在 ddlJobs 下拉列表中添加“--Select One--”作为索引 0。我在几个地方都试过了,比如page_load,formview的数据绑定事件都没有成功。

      Protected Sub ddlJobs_DataBinding(sender As Object, e As System.EventArgs)
      
          Dim ddlJobs As DropDownList = frmProfile.FindControl("ddlJobs")
          Dim liSelectOne As New ListItem("--Select One--", 0)
      
          ddlJobs.Items.Clear()
          ddlJobs.Items.Insert(0, liSelectOne)
      
      End Sub
      

      formview frmProfile_DataBound 事件的数据绑定事件确实做了一些工作。当用户在表单视图上单击“编辑”以进入编辑模式时,这可确保下拉列表 ddlJobs 默认为相关配置文件选择了正确的作业。如果用户尚未被分配到作业,则默认为 selectedindex 0,即上面自定义数据绑定事件中设置的“--Select One--”。

      Protected Sub frmProfile_DataBound(sender As Object, e As System.EventArgs) Handles frmProfile.DataBound
      
          If frmProfile.CurrentMode = FormViewMode.Edit Then
      
              Dim ddlJobs As DropDownList = frmProfile.FindControl("ddlJobs")
              Dim dvProfile As DataView = sqlDSProfile.Select(DataSourceSelectArguments.Empty)
              Dim drProfile As DataRow = dvProfile.Table.Rows(0)
      
              If drProfile("CurrentJobID").ToString() = "" Then
                  ddlJobs.SelectedIndex = 0
              Else
                  ddlJobs.SelectedValue = drProfile("CurrentJobID").ToString()
              End If
      
          End If
      
      End Sub
      

      最后,如果用户从 ddlJobs 中选择了一个新作业,则必须将该值提供给数据库,由 formview 的 ItemUpdating 事件处理。

      Protected Sub frmProfile_ItemUpdating(sender As Object, e As System.Web.UI.WebControls.FormViewUpdateEventArgs) Handles frmProfile.ItemUpdating
      
          If frmProfile.CurrentMode = FormViewMode.Edit Then
      
              Dim ddlJobs As DropDownList = frmProfile.FindControl("ddlJobs")
              e.NewValues("CurrentJobID") = ddlJobs.SelectedValue
      
          End If
      
      End Sub
      

      完成!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-06-22
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多