Programming Journal C#, Java, SQL and to a lesser extent HTML, CSS, XML, and regex. I made this so other programmers could benefit from my experience.

Showing posts with label C# AJAX. Show all posts
Showing posts with label C# AJAX. Show all posts

Wednesday, December 17, 2008

Using AutoComplete Ajax Control With Separate ID Field from Name Field

In the previous post, I detailed how to use the SQL stored procedure to select matches.

AutoComplete Extender offers a convenient way to select values froma TextBox. One problem is that multiple details can be displayed, but the whole text is selected by default. I wanted to allow multiple AutoCompletes, select the id without the other details and append the appropriate delimeter in between entries. First, I setup the WebService method. Note that the Stock object has Symbol and Name properties:

[WebMethod]
public string[] GetStocksInPrefix(string prefixText, int count)
{
int curCount = 0;
if (count == 0)
{
count = 10;
}
List<string> items = new List<string>();
JavaScriptSerializer jss = new JavaScriptSerializer();
string[] stocks = null;
string connectionString = getConnectionString("ConnectionString");
SqlDataReader rdr = null;
SqlConnection conn = new SqlConnection(connectionString);
System.Data.SqlClient.SqlCommand command = new System.Data.SqlClient.SqlCommand("sproc_aspnet_GetStocksByPrefix", conn);
try
{
command.CommandType = System.Data.CommandType.StoredProcedure;
conn.Open();
command.Parameters.AddWithValue("@Prefix", prefixText+"%");
rdr = command.ExecuteReader();
string tmp = string.Empty;
Stock _stock = null;
while (rdr.Read() && curCount<count )
{
_stock = new Stock(rdr["Symbol"].ToString(), rdr["Name"].ToString(), rdr["Exchange"].ToString());
tmp = rdr["Symbol"] + "\t" + rdr["Name"];
items.Add(AutoCompleteExtender.CreateAutoCompleteItem(tmp, jss.Serialize(_stock)));
curCount++;
}
command.Parameters.Clear();
}
catch (Exception ex)
{
}
finally
{
if (rdr != null) rdr.Close();
if(conn!=null) conn.Close();
}
return items.ToArray();
}


Then, I add the javascript event, 'OnSymbolSelected',to the OnClientItemSelected event in the AutoComplete Extender:

<asp:TextBox ID="txtSymbols" runat="server" Width="300px"></asp:TextBox>
<cc1:AutoCompleteExtender ID="AutoCompleteExtender1" runat="server"
TargetControlID="txtSymbols" ServiceMethod="GetStocksInPrefix"
ServicePath="~/WebServiceAutoCompleteSymbol.asmx" MinimumPrefixLength="2"
CompletionListHighlightedItemCssClass="watermark" CompletionSetCount="10"
DelimiterCharacters=", "
CompletionListElementID="Symbol"
CompletionListItemCssClass="watermarkMatch"
EnableCaching="true" CompletionInterval="1000" OnClientItemSelected="OnSymbolSelected"
>
</cc1:AutoCompleteExtender>


Finally, add the javascript function to the aspx page. This function reads the Stock object into results, takes the SelectedText and gets the original string before the new text was completed by replacing the completed text with an empty string. If it is an additional field (that does not contain ' ' or ',', then only the id (symbol in this case) is added. Othewise, the original id plus the ' ' delimeter and the new id is added:

<script type="text/javascript" language="javascript">
function OnSymbolSelected(source, eventArgs)
{
var results = eval('(' + eventArgs.get_value() + ')');
if (results.symbol != null) {
var symbols = document.getElementById('<%= txtSymbols.ClientID %>').value;
var original = symbols.replace((results.symbol+'\t'+results.name),'');
if (original.indexOf(' ')>0 || original.indexOf(',')>0)
document.getElementById('<%= txtSymbols.ClientID %>').value = original + (' '+ results.symbol);
else
document.getElementById('<%= txtSymbols.ClientID %>').value = results.symbol;
}
}
</script>


References: http://ziqbalbh.wordpress.com/2008/06/11/google-like-autocomplete-suggestions/
http://www.tizag.com/javascriptT/javascript-string-replace.php
http://techron.blogspot.com/2008/04/reading-textbox-or-other-control-values.html

Using LIKE in SQL

Be careful in the order of parameters while using LIKE in T-SQL. The following stored procedure did not work @Prefix LIKE dbo.aspnet_Stocks.Name. It must be reversed:

set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[sproc_aspnet_GetStocksByPrefix]
@Prefix as varchar(50)=NULL
AS
BEGIN
SELECT *
FROM dbo.aspnet_Stocks
WHERE ((Symbol LIKE @Prefix) OR ( [Name]LIKE @Prefix))
RETURN 0
END

This was used in an AutoComplete AJAX control. The following reference describes the setup.

Reference: http://www.aspdotnetcodes.com/AutoComplete_From_Database.aspx

A more efficient stored procedure would use a FullText Catalog indexed on a Text Column as described here: http://support.microsoft.com/?kbid=916784

Wednesday, April 2, 2008

Reading TextBox or other Control values with javascript

Reading TextBox or other Control values with javascript.
Assume TextBox ID="txtName"
First, there are the simple examples of a standard aspx page:


<script type="text/javascript" languague="javascript">
function simple1() {
var txtVal = $get('<%= txtName.ClientID %>').value;
}
function simple2() {
var txtVal = $document.getElementById('<%= txtName.ClientID %>').value;
}
</script>
Here is the complex sample used for accessing a MasterPage's updatePanel for example:

// In the ASPX class
private string scriptKey = "alertName";
private string script = "function alertName() { var txt = document.getElementById('[txtNameID]'); alert(txt.value); }";

// In the Page_Load event
script = script.Replace("[txtNameID]", txtName.ClientID);
ClientScript.RegisterClientScriptBlock(this.Page.GetType(), scriptKey, script, true);

references: http://www.velocityreviews.com/forums/t109803-callback-manager-masterpage.html

Thursday, March 20, 2008

Setting focus in a user control

Here is how to set focus in a user control. I used it in an update panel.

ScriptManager.GetCurrent(this.Page).SetFocus(txtTarget);

Tuesday, March 4, 2008

Prevent wrapping in table cell

Prevent wrapping in table cell. Since the old nowrap method is out of favor, the new method is to use:


<td style="white-space:nowrap"> foo </td>

reference: http://www.thescripts.com/forum/thread468471.html
Note: this also works with a Calendar Extender and TextBox even if the cell is too short.

Sunday, March 2, 2008

Previewing a TextBox that has HTML with a Popup Window

Here is a nifty way to preview HTML in a TextBox. I use the ScriptManager and $get the TextBox ID before popping the window and then filling it.

<script type="text/javascript" language="javascript" >
function preview() {
var txt= $get('txtContent');
var sHTML= txt.value;
win = window.open(", ", 'popup', 'toolbar = no, status = no');
win.document.write("" + sHTML + "");
}
</script>
Reference: http://javascript.internet.com/forms/html-preview.html

Wednesday, February 27, 2008

Lazy Load Panel Courtesy of TabContainer and UpdatePanel

Here is how I implemented a Lazy load Panel. This is a nifty way to have a mini-menu of tabs without some big data transfer happening all at once. The ASP.NET render after complete model makes incremental rendering a necessary task of the developer or else the users will take a hike. This is my adaptation of Matt Burseth's example that should be helpful to avoid the LESSTHAN%= and LESSTHAN%# problems that I had. Remember to put the js in the form tag (probably below the ScriptManager). Two parts below are the ASPX and Code Behind. ASPX:

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Lazy Load Panel Page</title>

</head>
<body>
<form id="form1" runat="server">
<ajax:ScriptManager ID="ScriptManager1" runat="server">
</ajax:ScriptManager>
<script type="text/javascript" language="javascript">
//var _updateProgressDiv;

function pageLoad(sender, args) {
// register for our eveents
Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(beginRequest);
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(endRequest);

//_updateProgressDiv = $get('ActionProgress');
}
function beginRequest(sender, args) {
// get the gridview element
var tabContainer = $get('<%= this.tcTest.ClientID %>');
alert(tabContainer);
// make it visible
// _updateProgressDiv.style.display='';
}
function endRequest(sender, args) {
// make it invisible
// _updateProgressDiv.style.display='none';
}

function clientActiveTabChanged(sender, args) {
// see if table elements for the grids exist yet
var isTab1Loaded = $get('<%= this.gv1.ClientID %>');
var isTab2Loaded = $get('<%= this.gv2.ClientID %>');
var isTab3Loaded = $get('<%= this.gv3.ClientID %>');

// if tab does not exist and it is the active tab, trigger the async-postback
alert(isTab1Loaded + ',' + isTab2Loaded + ',' + isTab3Loaded + ':' + sender.get_activeTabIndex());
if (!isTab1Loaded && sender.get_activeTabIndex() == 0) {
// load tab1
// alert('fire1');
__doPostBack('<%= btn1Trigger.UniqueID %>', '');
}
if (!isTab2Loaded && sender.get_activeTabIndex() == 1 ) {
// load tab2
// alert('fire2');
__doPostBack('<%= btn2Trigger.UniqueID %>', '');
}
if (!isTab3Loaded && sender.get_activeTabIndex() == 2 ) {
// load tab3
// alert('fire3');
__doPostBack('<%= btn3Trigger.UniqueID %>', '');
}
}
</script>
<input id="btn1Trigger" runat="server" type="button" style="display:none" onserverclick="btn1Trigger_Click" />
<input id="btn2Trigger" runat="server" type="button" style="display:none" onserverclick="btn2Trigger_Click" />
<input id="btn3Trigger" runat="server" type="button" style="display:none" onserverclick="btn3Trigger_Click" />

<div>
<ajaxc:TabContainer ID="tcTest" runat="server" OnClientActiveTabChanged="clientActiveTabChanged" ActiveTabIndex="0">
<ajaxc:TabPanel ID="tp1" runat="server" HeaderText="TabPanel1">
<ContentTemplate>
<ajax:UpdatePanel ID="upnl1" runat="server" UpdateMode="Conditional">
<ContentTemplate>
1<br />
<asp:GridView ID="gv1" runat="server" Visible="true" DataSourceID="sqlLicStatus">
</asp:GridView>
</ContentTemplate>
<Triggers>
<ajax:AsyncPostBackTrigger ControlID="btn1Trigger" />
</Triggers>
</ajax:UpdatePanel>
</ContentTemplate>
</ajaxc:TabPanel>

<ajaxc:TabPanel ID="tp2" runat="server" HeaderText="TabPanel2">
<ContentTemplate>
<ajax:UpdatePanel ID="upnl2" runat="server" UpdateMode="Conditional">
<ContentTemplate>
2<br />
<asp:GridView ID="gv2" runat="server" Visible="False" DataSourceID="sqlCondition" >
</asp:GridView>
</ContentTemplate>
<Triggers>
<ajax:AsyncPostBackTrigger ControlID="btn2Trigger" />
</Triggers>
</ajax:UpdatePanel>
</ContentTemplate>
</ajaxc:TabPanel>

<ajaxc:TabPanel ID="tp3" runat="server" HeaderText="TabPanel3">
<ContentTemplate>
<ajax:UpdatePanel ID="upnl3" runat="server" UpdateMode="Conditional">
<ContentTemplate>
3<br />
<asp:GridView ID="gv3" runat="server" Visible="False" DataSourceID="sqlCondition" >
</asp:GridView>
</ContentTemplate>
<Triggers>
<ajax:AsyncPostBackTrigger ControlID="btn3Trigger" />
</Triggers>
</ajax:UpdatePanel>
</ContentTemplate>
</ajaxc:TabPanel>

</ajaxc:TabContainer>
</div>





<asp:SqlDataSource ID="sqlLicStatus" runat="server"
ProviderName="System.Data.Bar"
DataSourceMode="DataReader"
ConnectionString="foo"
SelectCommand="SELECT foo FROM Validations WHERE bar=102 ORDER BY Code;">
</asp:SqlDataSource>
<asp:SqlDataSource ID="sqlCondition" runat="server"
ProviderName="System.Data.Foo"
DataSourceMode="DataReader"
ConnectionString="foo"
SelectCommand="SELECT foo FROM Validations WHERE bar=18 ORDER BY Code;">
</asp:SqlDataSource>
</form>
</body>
</html>
Code Behind:

/// <summary>
/// Lazy load TabPanel in a TabContainer
/// The update panel contents are fetched if client trigger is fired.
/// The client trigger is fired if the target tab is active and the
/// target GridView is not active (visible).
/// </summary>
public partial class Samples_LazyPanel : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{

}
protected void btn1Trigger_Click(object sender, EventArgs args)
{
this.gv1.Visible = true;
this.gv1.DataBind();
}
protected void btn2Trigger_Click(object sender, EventArgs args)
{
this.gv2.Visible = true;
this.gv2.DataBind();
}
protected void btn3Trigger_Click(object sender, EventArgs args)
{
this.gv3.Visible = true;
this.gv3.DataBind();
}
}

Saturday, February 16, 2008

FindContol Solution to add Javascript to a control from a user control

Here is a great solution to finding a control using FindControl method from a user control. TargetcontrolID is the public property for TextBoxFooExtender (User Control). _txt is the targeted TextBox assuming it is found.

protected override void CreateChildControls()
{
txt = (TextBox)this.Parent.FindControl(TargetControlID);
if (txt != null) {
_txt.Attributes.Add("ondblclick", "alert('foo')");
}
base.CreateChildControls();
}

Friday, February 15, 2008

How to show and hide CalendarExtender and CollapsiblePanel

Here is the javascript for expanding or collapsing a collapsible panel:


// Used for collapsible panels to toggle collapse or open
function CollapsiblePanelExtender_Toggle(behaviorId)
{
var behavior = $find(behaviorId);
if (behavior!=null) {
if (behavior.get_Collapsed()==false) {
try {behavior._doClose();} catch(e) { }
}else if (behavior.get_Collapsed()==true) {
try {behavior._doOpen();} catch(e) { }
}
}
}
// Used for calendar extenders to toggle show or hide
function CalendarExtender_Toggle(behaviorId) {
var behavior = $find(behaviorId);
if (behavior!=null) {
if (behavior._isOpen==true) {
try {behavior.hide();} catch(e) { }
}else if (behavior._isOpen==false) {
try {behavior.show();} catch(e) { }
}
}
}
The Calendar show and hide behavior is above. Note: it may be helpful to use an empty label/image for the calendarExtender popupcontrolId to manage show/hide behavior.

Thursday, November 29, 2007

How to implement Ajaxified details view hide on PageIndexChanging

Previously I showed how to enable DetailsView with a Select button (link). But here is how to get rid of the DetailsView if Paging is enabled by using the PageIndexChanging method.

protected void GridView1_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
// get rid of the details view
DetailsView1.DataSource = null;
DetailsView1.DataBind();

GridView1.PageIndex = e.NewPageIndex;
GridView1.DataBind();
}
To Ajaxify it within an update panel, add a Trigger for the Gridview1 object and the PageIndexChanging event.

Monday, November 26, 2007

Fixing WebForms.PageRequestManagerServerErrorException Status code 500

Here's a fix for the error WebForms.PageRequestManagerServerErrorException Status code 500.
I modified the MasterPage's ScriptManager as follows:

<asp:ScriptManager ID="ScriptManager1" runat="server" EnablePartialRendering="false">
</asp:ScriptManager>


UPDATE: This might fix the error, but it limits the functionality by not allowing Partial Page Rendering. This may not be acceptable. Here is a hint to avoid breaking the AJAX:

Hint: Be careful when changing Control names. The IDE won't catch the name change in the Extenders section of the TargetControlID.

Tuesday, September 25, 2007

Building an AJAX Slide Show in ASP.net

This was almost simple, but then the image paths made plug and chug necessary until the path problem was resolved. The key is to use image paths in the web service without ~/ and without /. Instead just type the directory name and the file name.



using System;
using System.Web;
using System.Collections;
using System.Web.Services;
using System.Web.Services.Protocols;


/// <summary>
/// Summary description for WebServiceSlideShow
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.Web.Script.Services.ScriptService()]
public class WebServiceSlideShow : System.Web.Services.WebService {

public WebServiceSlideShow () {

//Uncomment the following line if using designed components
//InitializeComponent();
}

[WebMethod]
public AjaxControlToolkit.Slide[] GetSlides() {
AjaxControlToolkit.Slide[] slides;
System.Collections.ArrayList alSlideUrls = new ArrayList();
alSlideUrls.Add("_imgLibrary/photo1.jpg");
alSlideUrls.Add("_imgLibrary/photo2.jpg");
alSlideUrls.Add("_imgLibrary/photo3.jpg");
slides = new AjaxControlToolkit.Slide[alSlideUrls.Count];
int i = 0;
foreach (string str in alSlideUrls)
{
slides[i] = new AjaxControlToolkit.Slide(str, str, str);
i++;
}
return slides;
}
}

Here is the ASPX code:


<div style="text-align: center">
<table style="vertical-align: text-top">
<tr>
<td style="width: 278px" nowrap="noWrap" align="center">
<asp:Image ID="ImagePlayer" runat="server" />
</td>
</tr>
<tr>
<td nowrap="nowrap" style="width: 278px" align="center">
<asp:Button ID="btnBack" runat="server" Text="Back" />
<asp:Button ID="btnPlay" runat="server" Text="Play" />
<asp:Button ID="btnNext" runat="server" Text="Next" />&nbsp;
</td>
</tr>
</table>
</div>
<cc1:SlideShowExtender ID="SlideShowExtender1" runat="server" TargetControlID="ImagePlayer" AutoPlay="True" Loop="True" NextButtonID="btnNext" PlayButtonID="btnPlay" PlayButtonText="Play" PreviousButtonID="btnBack" SlideShowServiceMethod="GetSlides" SlideShowServicePath="WebServiceSlideShow.asmx" StopButtonText="Pause">
</cc1:SlideShowExtender>