Двойное связывание данных, каскадное DropDownList к двум SqlDataSources в FormView - PullRequest
2 голосов
/ 07 февраля 2012

У меня есть два каскадных раскрывающихся списка, которые я пытаюсь связать с двумя отдельными источниками SqlDataSources.

Эти раскрывающиеся списки существуют в EditItemTemplate FormView.Внутри 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, который связывает всю информацию сТаблица сотрудников в заявлении об обновлении.Я оставляю всю другую информацию в этом 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.

Обновление

Я добавил tblEmployee.CurrentDeptID и tblEmployee.CurrentJobID в оператор select и добавил операторы Bind () в элементы управления DropDownList.

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

Теперь два DropDownLists заполнены.с точной информацией, извлеченной из таблицы Employee, показывающей отдел и должность, к которой принадлежит сотрудник.

Два DropDownLists также заполняются двумя SqlDataSources внутри FormView, что дает мне возможность изменить отдел и изменитьзадание.

Когда я меняю задание, оно работает, и задание сотрудников обновляется.

Когда я меняю отдел, оно прерывается, говоря DataBinding methods such as Eval(), XPath(), and Bind() can only be used in the context of a databound control.

Close to Done

Я удалил привязку данных из 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 я пытаюсь извлечь содержимое CurrentJobID из sqlDSProfile и проверить, существует ли это значение в 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

Ответы [ 3 ]

4 голосов
/ 13 декабря 2012

У меня была похожая проблема, и я нашел очень простое решение (и в c #). Представьте себе базу данных с таблицей вопросов, связанных с таблицами категорий и подкатегорий (которые также связаны и ограничены). При попытке обновить существующие записи asp выдает ошибку. Это решение, которое я разработал, благодаря информации, приведенной выше от Lucretius et al.

  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);
    }

Это работает на моем приложении. Надеюсь, это кому-нибудь поможет, этот стоил мне полдня, таков осел !!

2 голосов
/ 07 февраля 2012

Проблема может заключаться в том, что tlbEmployee столбцы в SqlDSProfile в операторе обновления и имена полей, используемые вашими элементами управления, не совпадают. Другие процедуры, которые вы выполнили, правильные.

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

Решением может быть: изменить все обновления Parameters на ControlParameter s, ссылаясь на правильный элемент управления для каждого

Обновление : подождите, я думаю, проблема в том, что ваш оператор select SqlDSProfile должен содержать: CurrentDeptID и CurrentJobID. Попробуйте:

<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 ... в запросах select
Избегайте ajax при тестировании
Если вы сделаете это
Добавьте порции кода после порции
наконец используйте частичное обновление (ajax)

1 голос
/ 10 февраля 2012

У меня есть рабочее решение, отчасти благодаря Nuux и куче онлайн-исследований.Подсказка об операторе соединения была неактуальной, но подсказка о включении «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"делает, добавляет" --Выберите One-- "в качестве индекса 0 в раскрывающемся списке ddlJobs.Я пробовал это в нескольких местах, таких как page_load, и событие привязки данных формы просмотра безуспешно.

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, это значение должно быть передано в базу данных, которую обрабатывает событие 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

Готово!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...