Ok, I give up, I need your help. I thought this'd be simple!
In this scenario, Departments belong to Institutions. In my SQL database, it's a one-to-many relationship. People belong to both Departments and Institutions. I'm writing a page which allows the editing of a Person's details, where the Departments to which they can belong are restricted according to the Institution to which they belong. For example, if the HR Department is part of Institution A and the Finance Department is part of Institution B, if the Person is in Institution A they cannot belong to the Finance Department unless you first move them to Institution B.
I've got two dropdownlists in a FormView for editing the person's details - ddlEditInstitution and ddlEditDepartment. Quite simply, when the FormView first enters Edit mode, I want these two dropdownlists to show the Institution and Department to which that Person currently belongs. If you click on the Department dropdownlist you will only be able to choose from Departments belonging to that Institution. If you change the Institution in ddlInstitution, the available options in ddlDepartment should refresh to only show Departments belonging to the newly-selected Institution.
Right, some code. Here's my mark-up for the dropdownlists:
<tr>
<td class="fieldlabel">Institution</td>
<td><asp:DropDownList ID="ddlEditInstitution" runat="server" DataTextField="Name" DataValueField="ID" DataSourceID="SQLInstitution" SelectedValue='<%# Bind("InstitutionID")%>' CssClass="contactdetailseditfield"
AutoPostBack="True" OnSelectedIndexChanged="ddlEditInstitution_SelectedIndexChanged" /></td>
<asp:SqlDataSource ID="SQLInstitution" runat="server" ConnectionString="<%$ ConnectionStrings:ContactsConnectionString %>"
SelectCommand="SELECT * FROM [Institution] WHERE ([Deleted] = 0)" />
</tr>
<tr>
<td class="fieldlabel">Department</td>
<td><asp:UpdatePanel ID="upDepartment" runat="server" UpdateMode="conditional">
<Triggers>
<asp:AsyncPostBackTrigger ControlID="ddlEditInstitution" EventName="SelectedIndexChanged" />
</Triggers>
<ContentTemplate>
<asp:DropDownList ID="ddlEditDepartment" runat="server" DataTextField="Name" DataValueField="ID" DataSourceID="SQLDepartment" CssClass="contactdetailseditfield" />
<asp:SqlDataSource ID="SQLDepartment" runat="server" ConnectionString="<%$ ConnectionStrings:ContactsConnectionString %>"
SelectCommand="SELECT * FROM [Department] WHERE ([Deleted] = 0) AND (Institution = #InstitutionID)">
<SelectParameters>
<asp:ControlParameter ControlID="ddlEditInstitution" PropertyName="SelectedValue" Name="InstitutionID" Type="Int32" />
</SelectParameters>
</asp:SqlDataSource>
</ContentTemplate>
</asp:UpdatePanel></td>
</tr>
And here's the code behind:
Protected Sub ddlEditInstitution_SelectedIndexChanged(sender As Object, e As EventArgs)
ddlEditDepartment.SelectedValue = Nothing
ddlEditDepartment.Items.Clear()
ddlEditDepartment.DataBind()
ddlEditDepartment.Items.Insert(0, New ListItem("--Select a department--", "-1"))
ddlEditDepartment.SelectedIndex = 0
End Sub
This almost works perfectly. The problem is that when the FormView first enters Edit mode, ddlEditDepartment does not display the Person's current Department, it displays the first Department in the dropdownlist's items. This makes sense - I haven't set the SelectedValue of ddlEditDepartment. However, if I do so (as I did originally, when I thought this would be easy) by adding the property to ddlEditDepartment in the page mark-up, like so...
SelectedValue = '<%# Bind("DepartmentID")%>'
... then what happens is that if you select a different option from ddlInstitution, the databound items for ddlDepartment don't update. They continue to be the options linked to the old Institution. Presumably this is because the SelectedValue property of ddlEditDepartment is overriding everything else - the dropdownlist is bound to that column no matter what, it seems.
I've tried getting around this every which way I can think of, by manually changing the SelectedValue of ddlEditDepartment in code behind when changing ddlEditInstitution, by trying to set the SelectedValue of ddlEditDepartment in code behind to the Person's current Department when the FormView first enters Edit mode rather than explicitly... But nothing works.
I hate dropdownlists in ASP.NET. Can anybody tell me how to achieve what seems like a relatively simple effect?
Finally figured out a way to do this. In the DataBound event of the FormView, if it's in Edit Mode, I manually get the Person's current Department and set ddlEditDepartment to that value.
Protected Sub fvContactDetails_DataBound(sender As Object, e As EventArgs) Handles fvContactDetails.DataBound
Dim dept As Integer = DataBinder.Eval(fvContactDetails.DataItem, "DepartmentID")
If fvContactDetails.CurrentMode = FormViewMode.Edit Then
ddlEditDepartment.SelectedValue = dept
End If
End Sub
Related
I am having an issue trying to change SelectCommand contents dynamically.
There is this Telerik searchbox control that uses SQLDataSource to constantly bang the DB with a select query and show up a list of words filtered by your typing. Then if you pick an entry from the list it will become a "token" and then you can start typing again.
In my case, the query should return a list of car makes and the initial query is:
SELECT DISTINCT mfrname
FROM Manufacturers
WHERE mfrname IS NOT NULL
ORDER BY mfrname
So if I type "Che" it will show up "Checker" and "Chevrolet". So if I click "Chevrolet" it will become a token and my typing is reset so I can start typing again.
For tests purposes after the token is generated I slighted changed my query to:
SELECT DISTINCT mfrname
FROM manufacturers
WHERE mfrname IS NOT NULL and mfrname like 'm%'
ORDER BY mfrname
Notice that now it should only select the car makes started with an "M" like "Mercedes", "Maseratti", etc, so if I type anything else that doesn't starts with an "M" it shouldn't show anything.
However if I type "Che" there it is "Checker" and "Chevrolet" again, making it clear that it's still using the initial query and not the new one.
OKay, I know that the event IS being triggered and the SelectCommand value IS being changed (I know this because I added a label that changes and shows up the new value). What I don't know is why the control insists on keep using the old query and not the new one! Any idea?
My code front:
<form id="form1" runat="server">
<telerik:RadScriptManager runat="server" ID="RadScriptManager1" />
<telerik:RadAutoCompleteBox RenderMode="Lightweight" runat="server" ID="RadAutoCompleteBox1" autopostback="true" EmptyMessage="Type in car make..."
DataSourceID="SqlDataSource1" DataTextField="mfrname" InputType="Token" Width="450" DropDownWidth="150px" OnEntryAdded="RadAutoCompleteBox1_EntryAdded" >
</telerik:RadAutoCompleteBox>
<asp:SqlDataSource runat="server" ID="SqlDataSource1" CancelSelectOnNullParameter="false" ConnectionString="<%$ ConnectionStrings:MyConn %>" SelectCommand="SELECT DISTINCT mfrname FROM Manufacturers WHERE mfrname IS NOT NULL ORDER BY mfrname">
</asp:SqlDataSource>
<div>
<br />
<asp:label id="label1" runat="server">Waiting for update...</asp:label>
</div>
</form>
My code behind:
Protected Sub RadAutoCompleteBox1_EntryAdded(sender As Object, e As Telerik.Web.UI.AutoCompleteEntryEventArgs)
SqlDataSource1.SelectCommand = "SELECT DISTINCT mfrname FROM manufacturers WHERE mfrname IS NOT NULL and mfrname like 'm%' ORDER BY mfrname"
RadAutoCompleteBox1.DataBind()
label1.Text = e.Entry.Text + " was added. (" + SqlDataSource1.SelectCommand + ")"
End Sub
I found the solution. Well, more like a work around but it works.
In my case I didn't need to change entirely the query, but actually only the WHERE clause. So I added a dynamic parameter to the query text and tied it to another control (an invisible label) forcing the AutoCompleteBox to always look into the contents of the label before to run the query.
This way, changing the contents of the label will change the parameter used in my WHERE clause and so I can control the query. It may be expanded by simply adding more parameters to the SQLDataSource and adding additional invisible controls to the page.
So here it goes the implemented solution since it may be of help for someone else...
Code front:
<form id="form1" runat="server">
<telerik:RadScriptManager runat="server" ID="RadScriptManager1" />
<telerik:RadAutoCompleteBox RenderMode="Lightweight" runat="server" ID="RadAutoCompleteBox1" autopostback="true" EmptyMessage="Type in car make..." DataSourceID="SqlDataSource1" DataTextField="mfrname" InputType="Token" Width="450" DropDownWidth="150px" OnEntryAdded="RadAutoCompleteBox1_EntryAdded" >
</telerik:RadAutoCompleteBox>
<asp:SqlDataSource runat="server" ID="SqlDataSource1" CancelSelectOnNullParameter="false" ConnectionString="<%$ ConnectionStrings:MyConn %>" SelectCommand="SELECT DISTINCT mfrname FROM Manufacturers WHERE mfrname like #mypar and mfrname IS NOT NULL ORDER BY mfrname">
<SelectParameters>
<asp:ControlParameter ControlID="lblSQLpar" Name="mypar" PropertyName="Text" />
</SelectParameters>
</asp:SqlDataSource>
<div>
<!-- initial value -->
<asp:label id="lblSQLpar" runat="server" Visible="false">%</asp:label>
</div>
</form>
code behind:
Protected Sub RadAutoCompleteBox1_EntryAdded(sender As Object, e As Telerik.Web.UI.AutoCompleteEntryEventArgs)
'Use CASE structure to change the parameter accordingly to your needs
lblSQLpar.Text = "m%"
End Sub
I am binding a dropdown for location with a select statment
Select location_id, location_name,businessid from inventory.tbl_location order by location_name
I want to put the first element as 'Select location'. Right now I am getting all locations. How to set initial value as Select in the dropdown of asp.net page that is databound with sql statement?
In the aspx page :
<asp:DropDownList ID="ddlAllLocations" runat="server" DataSourceID="SqlDataSourceBusinessLocations"
DataTextField="Location_Name" DataValueField="Location_ID" AutoPostBack="True">
</asp:DropDownList>
And
<asp:SqlDataSource ID="SqlDataSourceBusinessLocations" runat="server" ConnectionString="<xxxxxx>"
ProviderName="<%$ zzzzz %>" SelectCommand="Select location_id, location_name,businessid from inventory.tbl_location order by location_name" FilterExpression="businessid in ({0})">
<FilterParameters>
<asp:SessionParameter DefaultValue="0" Name="BUID" SessionField="BusinessUnitIDs" />
</FilterParameters>
</asp:SqlDataSource>
I added the code as suggested in the page_load event, here is another problem, everytime it is adding select location to the list items
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If IsPostBack() Then
lblError.Text = ""
ddlAllLocations.Items.Insert(0, New ListItem("Select location"))
End If
End Sub
Try this:
<asp:DropDownList ID="ddlAllLocations" runat="server"
DataSourceID="SqlDataSourceBusinessLocations"
DataTextField="Location_Name"
DataValueField="Location_ID"
AutoPostBack="True"
AppendDataBoundItems="True">
<asp:ListItem value="" selected="True">
Select
</asp:ListItem>
</asp:DropDownList>
Don't forget the AppendDataBoundItems attribute. Be careful using this in an update panel: each update will re-append all the items and you'll end up with duplicates. In that case, you might be able to fix it by disabling ViewState for the control.
Not sure how you do the databinding but I hope you're doing it in code-behind...
In that case it's pretty straighforward:
mydroplist.DataSource = someSource;
mydroplist.DataBind();
mydroplist.Items.Insert(0, new ListItem("Select location"));
edit based on your edit:
it's not a good idea to have SQL in your UI.. That's a very bad design. Do some research on proper programming architectures, how to separate layers etc. Then you will do the databinding in code-behind and my sample will help you.
If you insist on using your way of doing things, you can simply wire up the event when the dropdownlist is databound and add this piece of code (except the binding part of course)
I want to populate a dropdown list with values from a table I created. I only want to populate the list with one of the fields- the languages in my table. I think I have connected to the data source correctly, but I don't know what I have to do to get the values into the list. I can enter my own values but I'd rather have this automated.
This is what I have so far, but I'm guessing there's more to it than just linking the list to the data source.
<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:HBshareIndexConnectionString %>"
SelectCommand="SELECT * FROM [Web_Metrics] WHERE ([LCID] = #LCID)">
<SelectParameters>
<asp:QueryStringParameter Name="LCID" QueryStringField="LCID" Type="Int32" />
</SelectParameters>
</asp:SqlDataSource>
<asp:Label ID="Label1" runat="server" Text="Select LCID: " ></asp:Label>
<asp:DropDownList ID="DropDownList1" Width="150px" runat="server" DataSourceID="SqlDataSource1" DataTextField="LCID" DataValueField="LCID">
<asp:ListItem>Select LCID...</asp:ListItem>
</asp:DropDownList>
Thanks for the help. I got the dropdown list populated now, but I was wondering how do I actually get the repeater I'm using to display the details of the LCID the person selects? I've seen people talking about page.isPostback but I don't know what that is or if it works with my current setup. I need to somehow get the LCID they selected and then refresh the page to show the details of that LCID. Does anyone have any ideas?
Your problem is that you're trying to define list items and a data source.
If you want to insert a "Select an item.." option, I would suggest prepending it to your resultset (getting it to always be first with a UNION and ORDER BY could be difficult depending on your fields) or inserting it after databinding in your code behind:
Modification to DropDownList1s attributes:
<asp:DropDownList ID="DropDownList1" Width="150px" runat="server" DataSourceID="SqlDataSource1" DataTextField="CountryName" DataValueField="LCID" OnDataBound="InsertChooseItem" />
C#:
protected void InsertChooseItem(object sender, EventArgs e)
{
ListItem selectOnePlease = new ListItem("Select LCID..", 0);
DropDownList1.Items.Insert(0, selectOnePlease);
}
VB:
Protected Sub InsertChooseItem(sender As Object, e As EventArgs)
Dim selectOnePlease As New ListItem("Select LCID..", 0)
DropDownList1.Items.Insert(0, selectOnePlease)
End Sub
You've specified the select parameter to be a query string, so the data in your DropDownList will only be populated when the URL resembles something like:
http://{Your server name}/Default.aspx?LCID=1
That doesn't make any sense though because the LCID column in your table should be unique, so although this will work there will only be one value in the drop down list.
I think what you want is to display all the languages from the database in the drop down, here's an example:
<asp:SqlDataSource ID="sqlDS" runat="server"
ConnectionString="<%$ ConnectionStrings:HBshareIndexConnectionString %>"
SelectCommand="SELECT LCID,Language FROM [Web_Metrics]">
</asp:SqlDataSource>
<asp:DropDownList ID="ddlLanguages" AppendDataBoundItems="true" Width="150px" runat="server" DataSourceID="sqlDS" DataTextField="Language" DataValueField="LCID">
<asp:ListItem>Select Language</asp:ListItem>
</asp:DropDownList>
Just a note, you should never display the ID to the client, it's totally meaningless to them, the ids are mostly used by developers in the background that's why in the drop down I set the:
DataTextField="Language" (This is the language name visible to the user)
DataValueField="LCID" (Not visible to the user, but useful for any additional processing in code behind)
AppendDataBoundItems="true" - this line of code will keep all the items you've manually added to the drop down, e.g "Select Language" and will append any data bound items e.g from a SQL table
I have two cascading dropdown lists I'm attempting to bind to two separate SqlDataSources each.
These dropdownlists exist in a FormView's EditItemTemplate. Inside the EditItemTemplate two sqldatasource controls exist that populate the department and the jobname. The DeptID and the JobID are the primary keys in those tables. This creates the "cascading effect" between departments and jobs. When a department is selected, only the jobs associated with that department appear.
This piece is working properly.
<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>
Outside the formview the SqlDataSource exists that binds all of the information to the Employee table in an update statement. I'm leaving all of the other information in this SqlDataSource even though it's been omitted from the FormView above.
<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>
The only pieces I can't figure out how to bind are the Departments and the Jobs. Everything else is working. I've tried using the following code in the DropDownList controls...
SelectedValue='<%# Bind("CurrentDeptID") %>'
SelectedValue='<%# Bind("CurrentJobID") %>'
...but these result in errors.
Summary
When the user clicks edit, I need the values in the two dropdownboxes to pull their selectedvalue from the main sqlDSProfile data source, but I need them to be updatable. I've gotten it to the point where I can update and bind the job that an associate belongs to, but because the dropdownlists cascade, when I attempt to change the department the AutoPostBack breaks the binding between sqlDSProfile - CurrentJobID and ddlJobs.
Update
I added tblEmployee.CurrentDeptID and tblEmployee.CurrentJobID to the select statement, and added Bind() statements to the DropDownList controls.
SelectedValue='<%# Bind("CurrentDeptID") %>'
SelectedValue='<%# Bind("CurrentJobID") %>'
The two DropDownLists are now populated with accurate information pulled from the Employee table, showing the department and job that the employee belongs to.
The two DropDownLists are also populated by the two SqlDataSources inside the FormView, giving me options for changing the department and changing the job.
When I change the Job, it works and the employees job is updated.
When I change the Department, it breaks saying DataBinding methods such as Eval(), XPath(), and Bind() can only be used in the context of a databound control.
Close to Done
I removed the data binding from ddlJobs and coded that in the background.
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
The only piece that's left is building the code for when the ddlDepartments changes.
pseudocode...
' If Item exists in ddlJobs Then
' select item (CurrentJobID)
' else
' select index 0 and make them pick something new
' end if
So Close!
Updated Again
This is the code I've developed to loosely bind this. In the page_load I'm trying to pull the contents of CurrentJobID from sqlDSProfile and check to see if that value exists in ddlJobs. If it does I want to set ddlJobs.SelectedValue = to that CurrentJobID. If it doesn't I want to set the selectedindex to 0 which is a message saying "pick one" or something.
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
Its returning a null reference exception on the line where I'm checking for dbnull.value
I had a similar issue and found a very simple resolution, (and in c#). Imagine a database with a table Questions, related to category and subcategory tables (which are also related and constrained). When trying to update existing records asp throws an error. This is the solution that I worked out thanks to the information above from Lucretius et al.
Only databind the parent dropdownlist
Find a way to insert the child dropdown selected value on the update event of the datasource.
As:
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);
}
It works on my application. Hope it helps somebody, this one cost me half a day, such is asp!!
The problem can be if tlbEmployee columns in the SqlDSProfile in the update statement and field names used by your controls do not match. Other procedures you've followed are right.
SqlDataSource control expects field names it updates to be similar
with those bound to the controls(fields) inside the DataBound control.
The Solution can be: change all the update Parameters to ControlParameters referencing the right control for each one
Update: Wait, I think the problem is your select statement of the SqlDSProfile should contain: CurrentDeptID and CurrentJobID. Try it:
<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
Advice: Test your code portion by portion.
Try the code without the dropdownlist, Test separately
Add the one drop downlist
Use select * from ... in select queries
Avoid ajax when testing
If you make it
Add portions of code portion after portion
at last use the partial updating (ajax)
I have a working solution now, thanks in part to Nuux and a bunch of online research. The tip about the join statement wasn't relevant, but the tip about including "CurrentJobID" and "CurrentDeptID" in my select query was spot on.
In addition to that I had to rework the controls a little. The two cascading dropdownlists are below. The ddlJobs dropdown list behaves like a normal databound control, but it doesn't have the Bind("CurrentJobID") statement I was trying in my original post.
<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" />
The only thing the custom routine "ddlJobs_DataBinding" is doing is adding "--Select One--" as index 0 in the ddlJobs dropdown. I tried this in several places, like page_load, and the databound event of the formview with no success.
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
The databound event of the formview frmProfile_DataBound event does do some work though. When the user clicks "edit" on the formview to enter editing mode this ensures that the dropdownlist ddlJobs has the correct job selected by default for the profile in question. If the user hasn't been assigned to a job then it defaults to selectedindex 0 which is "--Select One--" set in custom databinding event just above.
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
Finally, if the user selects a new job from ddlJobs, that value has to be fed to the database, which the ItemUpdating event of the formview handles.
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
Done!
I have a master-detail page for Customers. Select a customer from the list and a details view opens with Name, Address...etc.
I've been asked to add a field listing the Sales Rep servicing that customer.
I want the new field to hold the foreign key to the SalesRep table: the SalesRepID. An integer.
I am not sure how to "wire up" the ItemTemplate field for displaying the Sales Rep name in a label. Also not sure about the EditItemTemplate dropdown list of possible Sales Reps.
I know I need to create a datasource to retreive the Sales Reps into a dataSet.
Let's call it "SQL_Reps_source".
A DropDownList seems to only like a list of values, and doesn't seem to handle Keys and Values like a HashTable or SortedList would.
Any advice on how to go about this?
Thanks
The following example adds a DropDownList to the EditItemTemplate of the DetailsView. The DataSourceID is set to the data source control that retrieves the sales reps names and id's.
<asp:TemplateField HeaderText="Sales Rep">
<EditItemTemplate>
<asp:SqlDataSource ID="SqlDataSource" runat="server"
ConnectionString="<%$ ConnectionStrings:MyConnectionString %>"
SelectCommand="SELECT SalesRepID, SalesRepName FROM SalesReps">
</asp:SqlDataSource>
<asp:DropDownList ID="DropDownList" Runat="server"
DataTextField="SalesRepName" DataValueField="SalesRepID"
SelectedValue='<%# Bind("SalesRepID") %>'
DataSourceID="SqlDataSource">
</asp:DropDownList>
</EditItemTemplate>
<ItemTemplate>
<asp:Label ID="Label" Runat="server"
Text='<%# Bind("SalesRepName") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
For display purposes - return the NAME of the Sales Rep. rather than ID
DropDownList (ddl) handles both Values and Keys just fine, the naming is a bit off though. ddl.DataTextField property will hold the Name, ddl.DataValueField property will hold the ID. (see this answer for more details on this)
In the EditTemplate you'd need to fill the DropDown as described above, and then set its SelectedValue to the ID of Sales Rep. in quesion.
Hope this helps.
When you bind the dropdownlist do this:
ddl.DataSource = SQL_Reps_source;
ddl..DataTextField = "fullname";
ddl..DataValueField = "id";