Cannot change SelectCommand contents dynamically - asp.net

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

Related

Databound Child Master Dropdownlist

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

How to set initial value as Select in the dropdown of asp.net page that is databound with sql statement

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)

How to populate a dropdown list in asp.net from a DB table?

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

How do you have multiple controls for a gridview?

For example, I have a gridview and two textboxes.
One textbox is for the text to search for.
The second textbox is an order number to search for.
I want my gridview to populate based on one or the other. I don't know how to tell my form if the user is using a number search by that and if a name, instead search by that.
Thanks for any help.
OK hope you haven't solved this yet because I took a few minutes to come up with an example that I think will do pretty much what you want.
DB access uses a stored procedure but you can use a ObjectDataSource with DAL, or just inline the SQL statement on the SqlDataSource, etc.
Markup:
Product ID:
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<asp:CompareValidator ID="CompareValidator1" ControlToValidate="TextBox1" runat="server" ErrorMessage="You must enter a number"
ValidationGroup="vg1" Type="Integer" Operator="DataTypeCheck"></asp:CompareValidator>
<br />
Description:
<asp:TextBox ID="TextBox2" runat="server"></asp:TextBox><br />
<asp:Button ID="cmdSearch" runat="server" Text="Search" ValidationGroup="vg1" /><br />
<asp:GridView ID="GridView1" runat="server" DataSourceID="SqlDataSource1">
</asp:GridView>
<asp:SqlDataSource ID="SqlDataSource1" runat="server" SelectCommand="spGetProducts"
CancelSelectOnNullParameter="False" SelectCommandType="StoredProcedure">
<SelectParameters>
<asp:ControlParameter ControlID="TextBox1" PropertyName="Text" DbType="String" DefaultValue="" />
<asp:ControlParameter ControlID="TextBox2" PropertyName="Text" DbType="Int32" DefaultValue="" />
</SelectParameters>
</asp:SqlDataSource>
And T-SQL for your query:
CREATE PROCEDURE spGetProducts
#ProductId int = NULL
,#ProductDescription nvarchar(100) = NULL
AS
BEGIN
SELECT [ProductId]
,[ProductDescription]
FROM [Products]
WHERE (
(
(#ProductId IS NULL)
OR
([ProductId] LIKE % + #ProductId + %)
)
AND
(
(#ProductDescription IS NULL)
OR
([ProductDescription] LIKE % + #ProductDescription + %;)
)
);
END
If the user doesn't enter anything in either of the fields, the SqlDataSource will still bind due to SqlDataSource.CancelSelectOnNullParameter = False but the empty parameter will not be sent with the query due to ControlParameter.DefaultValue being set. The stored procedure will then insert the NULL value into the parameter and basically skip that part of the filtering in the WHERE clause.
Hope this helps.
You can check the textboxes by using (TextBox1.Text.Trim.Length > 0) or (TextBox1.Text = "")
It sounds like what you are really asking is how do you filter your data source based on more than one possible filter parameter. Explaining that would require knowing what your data source is. Either way, the gridview is just going to display the filtered results, right?
If you are using SQL for your data source the technique is going to be totally different than filtering a collection in memory. So more information on that would be helpful.

ASP.NET DropDownList bound to data but allows for nulls?

I'm using LINQ to SQL and want to be able to select a parent or no parent. Let's say I have a People table with PersonId, Name and ParentId columns. In ASP I want to enter the name, select a parent and click 'Add' to create a new Person record, but I also want to be able to leave the ParentId null. Don't ask why, this is just a simplified explanation for what I want to do.
<asp:LinqDataSource ID="LinqPeople" runat="server"
ContextTypeName="MyDataContext" EntityTypeName=""
Select="new (PersonId, Name)" TableName="People"/>
<asp:TextBox ID="textName" runat="server" />
<asp:DropDownList runat="server" ID="dropParent"
DataSourceID="LinqPeople" DataTextField="Name" DataValueField="PersonId" />
<asp:Button ID="buttonAddPerson" runat="server" Text="Add" />
Is there any way to display 'None' in the list box with a value of null? I have thought of a few options, which is best or are there any others?
Create a stored procedure for the SQL "SELECT PersonId, Name FROM People UNION SELECT Null, 'NONE'"
Add a CheckBox for "NO PARENT"
Put a ListItem in the markup for the DropDownList
Add the item on the DataBound event handler
I found a better way, adding a ListItem in the markup:
<asp:LinqDataSource ID="LinqPeople" runat="server"
ContextTypeName="MyDataContext" EntityTypeName=""
Select="new (PersonId, Name)" TableName="People"/>
<asp:TextBox ID="textName" runat="server" />
<asp:DropDownList runat="server" ID="dropParent"
DataSourceID="LinqPeople" DataTextField="Name" DataValueField="PersonId">
<asp:ListItem Value="">(none)</asp:ListItem>
</asp:DropDownList>
<asp:Button ID="buttonAddPerson" runat="server" Text="Add" />
I cannot find any way to return the actual value 'NULL' in SelectedValue however, but I can handle that I guess. I think the ListItem way is the best because it is defined in the markup and doesn't require any code...
Don't think you can set the value of NULL since it's a string type.
I don't like the check for NULL, typically, I would use something that doesn't make sense, like -1 or something and check for that. You could also assume that your selected index is 0, however, that could cause problems somewhere else in code if you don't follow throughout the app.

Resources