ListView with DataPager problem in .Net 4

by aboo bolaky 31. October 2010 00:36

I wanted to set the QueryStringField property of the DataPager dynamically. By default, if you do not specify this property, the pager works on a Postback Model.

On the other hand, if you do set the QueryStringField to something, it'll use the value that you set the QueryStringField to as a query string parameter and assign it the appropriate page number (IOW, it makes use of a query string parameter to change the page view)

The declarative and code-behind files are simple enough..

 

 

public partial class _Default : System.Web.UI.Page
{
        public string FieldName
        {
            get
            {
                return "PageID";
            }
        }
        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);
            
            ListView1.PagePropertiesChanging += new EventHandler(ListView1_PagePropertiesChanging);
            DataPager1.QueryStringField = FieldName;
           
        }
       

        void ListView1_PagePropertiesChanging(object sender, PagePropertiesChangingEventArgs e)
        {
            DataPager1.SetPageProperties(e.StartRowIndex, e.MaximumRows, false);
            BuildAndBind();

        }
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!this.IsPostBack)
            {
                BuildAndBind();
            }

        }
        private void BuildAndBind()
        {
            ListView1.DataSource = BuildDataSource();
            ListView1.DataBind();

        }
        private List BuildDataSource()
        {
            Person a = new Person { FirstName = "A", LastName = "A", Address = "Address1" };
            Person b = new Person { FirstName = "B", LastName = "B", Address = "Address2" };
            Person c = new Person { FirstName = "C", LastName = "C", Address = "Address3" };
            Person d = new Person { FirstName = "D", LastName = "D", Address = "Address4" };
            Person e = new Person { FirstName = "E", LastName = "E", Address = "Address5" };
            Person f = new Person { FirstName = "F", LastName = "F", Address = "Address6" };
            Person g = new Person { FirstName = "G", LastName = "G", Address = "Address7" };
            Person h = new Person { FirstName = "H", LastName = "H", Address = "Address8" };
            Person i = new Person { FirstName = "I", LastName = "I", Address = "Address9" };
            Person j = new Person { FirstName = "J", LastName = "J", Address = "Address10" };
            Person k = new Person { FirstName = "K", LastName = "K", Address = "Address11" };
            Person l = new Person { FirstName = "L", LastName = "L", Address = "Address12" };
            Person m = new Person { FirstName = "M", LastName = "M", Address = "Address13" };


            List list = new List();
            
            list.Add(a);
            list.Add(b);
            list.Add(c);
            list.Add(d);
            list.Add(e);
            list.Add(f);
            list.Add(g);
            list.Add(h);
            list.Add(i);
            list.Add(j);
            list.Add(k);
            list.Add(l);
            list.Add(m);

            return list;
        }
    }

So far...So good..

Using the above example, since we've set the property in the code behind, we'd expect the pager to use a query string to drive the page view. Commenting the line out forces the pager to use a postback model.

What about .Net 4?

the above situations work when the project is set up to run in .NET 3.5 . However, this solution does not seem to work with .NET 4.0 at all. If we set the Target Framework to 4.0, the paging does not work if we want to force a QueryStringField at runtime :(

I've  attached a copy of the vs2010 website here

TestWebApp.zip (2.44 kb)

and the video (in mp4 format...) here

DataPager.mp4 (5.27 mb)

If there's anyone out there who can give me a clue on what's right or wrong, please drop me a few lines.. :)

 

Tags:

.Net | Asp.Net

Registering XSLT Extension Objects with the ASP XML control

by aboo bolaky 23. October 2009 07:01

I once inherited a sublayout that inlcuded an asp:xml control. The asp:xml control was there to handle and display an xml feed from another system, while the rest of the sublayout concentrated on rendering related feed content from Sitecore. The presentation of the xml feed was handled via an xlst rendering.

In this particular situation, I made use use of XSL extensions in the XSLT file. Registering the XSL Extension was fairly easy.

   
<xslExtensions>   
	<extension mode="on" type="Utils.XslHelper, Utils"
	           namespace="http://www.sitecore.net/Utils" 
		   singleInstance="true" />
	   .....
</xslExtensions>



Registering the extension in the xsl file

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:MyExtension="http://www.sitecore.net/Utils"
 exclude-result-prefixes="MyExtension" >

<xsl:value-of select="MyExtension:HelloWorld()" />



Binding the XML control to the XML Data

protected override void OnInit(EventArgs e)
    {
        if (!this.IsPostBack)
        {
            string xmlContent = "xml data goes here";
            XsltArgumentList list = new XsltArgumentList();
            Utils.XslHelper ext = new Utils.XslHelper();
            list.AddExtensionObject("http://www.sitecore.net/Utils", ext);
            Xml1.TransformArgumentList = list;
            Xml1.DocumentContent = xmlContent;
        }
    }

It turns out that, even though I had previously registered the xsl extension in the xslt file, I also had to register it via code as well. Otherwise, the following exception occurs at runtime.

Cannot find the script or external object that implements prefix 'MyExtension'.

Sorted!

Tags: ,

.Net | Asp.Net | Sitecore | Tips & Tricks

Bold style for matching results with AutoCompleteExtender - Implemented using a Trie

by aboo bolaky 7. October 2009 18:22

This article will focus on the implementation of the AjaxControlToolkit's AutoCompleteExtender into a simple ASP.NET application. What I'm trying to do here is pull the data from a database and use the AutoCompleteExtender to display the data as the user types characters in a textbox.

Server Implementation

Im not going to focus on how to retrieve the data (from a table of around 60,000 records). I'm going to use the simplistic SQLConnection/SQLCommand/SQLDataReader classes and passing sql command as plain text (as opposed to Stored Procedures). The key issue is how and what is the best way to store the data once being retrieved. Generally, Autocomplete comes in 2 flavours:-

1: Find words based on letters anywhere in a phrase (performing a LIKE '%ar%'  in SQL).

2: Find words that start with specific characters ( LIKE 'ar%' in SQL).

In the first instance, you're pretty much tied up to using the LIKE clause (be it in a stored proc or simple text). The determining factor here is how and when to cache the data since each character typed in invokes the webservice and queries the database. Each query will yield a different result set.

In the second instance (the focus of this article), the more you add characters to the keyword, you are, in fact, narrowing down the scope of search. This means that the data we initially load is deterministic and hence we can cache it somewhere. But the real deal here is :which  data structure do we hold our words in? List<>, DataTable, Linked List??

Trie 

You might have already figured this one out. Anyway, a trie is an ordered tree data structure (a.k.a prefix tree) that stores the information about the contents of each node in the path from the root to the node, rather than the node itself. What this means is that each part between the root and any leaf represents a key and the goal is to find the key by traversing the tree.

Implementation

Eyal Mey-Tal has implemented a Trie structure in C#.Head to the CodePlex site to download it.

WebMethod to retrieve data

[WebMethod]
    public string[] GetNames(string prefixText, int count)
    {
        Trie trie = (Trie)Context.Cache["Trie"];
        if (trie == null)
        {
            trie = new Trie();
            using (SqlConnection con = new SqlConnection("server=(local);database=autocomplete;user id=xxx;Password=xxx;"))
            {
                SqlCommand cmd = new SqlCommand("select word from AutoCompleteData", con);
                cmd.CommandType = System.Data.CommandType.Text;
                con.Open();
                SqlDataReader dr = cmd.ExecuteReader();
                if (dr.HasRows)
                {
                    while (dr.Read())
                    {
                        trie.Add(dr.GetString(0));
                    }
                    con.Close();
                }
            }
            //simple caching here  
            Context.Cache["Trie"] = trie;
        }
        List list = trie.GetCompletionList(prefixText);
        return list.Take(count).ToArray();
    }

 

Setting up the AutoCompleteExtender was easy. To get the autocomplete working, I only had to modify a few of the extender's attributes (.e.g. CompletionSetCount, TargetControlID, ServicePath, ServiceMethod, DelimiterCharacters ..) and data was being returned as I typed in characters. However, making the extender look good was a different story.

Client-Side Implementation 

This is the bit where I'm open to suggestions. I'm no Javascript/JQuery expert but however, I finally got the extender working as I wanted it to. Characters relevant to the ones the user has typed become highlighted in the drop down list. It took me a while to dig this solution out. The javascript is awkward and needs to be refactored. Netherless, the solution works for IE and Firefox [ good enough for me :) ]

 

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="AutoComplete.aspx.cs" Inherits="AutoComplete.AutoComplete" %>
<%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="cc1" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
    <title></title>
    <style>
        .autocomplete_completionListElement
        {
            margin: 0px !important;
            background-color: inherit;
            color: windowtext;
            border: buttonshadow;
            border-width: 1px;
            border-style: solid;
            cursor: 'default';
            overflow: auto;
            height: 200px;
            text-align: left;
            list-style-type: none;
            padding-left: 1px;
        }
        
        /* AutoComplete highlighted item */
        
        .autocomplete_highlightedListItem
        {
            background-color: #aaff90;
            color: black;
            padding: 1px;
            cursor: hand;
        }
        
        /* AutoComplete item */
        
        .autocomplete_listItem
        {
            background-color: window;
            color: windowtext;
            padding: 1px;
        }
    </style>
    <script type="text/javascript">

        function acePopulated(sender, e) {

            var behavior = $find('AutoCompleteEx');

            var target = behavior.get_completionList();
            if (behavior._currentPrefix != null) {
                var prefix = behavior._currentPrefix.toLowerCase();
                var i;
                for (i = 0; i < target.childNodes.length; i++) {
                    var sValue = target.childNodes[i].innerHTML.toLowerCase();
                    if (sValue.indexOf(prefix) != -1) {
                        var fstr = target.childNodes[i].innerHTML.substring(0, sValue.indexOf(prefix));
                        var pstr = target.childNodes[i].innerHTML.substring(fstr.length, fstr.length + prefix.length);
                        var estr = target.childNodes[i].innerHTML.substring(fstr.length + prefix.length, target.childNodes[i].innerHTML.length);
                        target.childNodes[i].innerHTML = "<div class='autocomplete-item'>" + fstr + '<B>' + pstr + '</B>' + estr + "</div>";
                    }
                }
            }

        }

        function aceSelected(sender, e) {
            var value = e.get_value();
            if (!value) {
                if (e._item.parentElement && e._item.parentElement.tagName == "LI")
                    value = e._item.parentElement.attributes["_value"].value;
                else if (e._item.parentElement && e._item.parentElement.parentElement.tagName == "LI")
                    value = e._item.parentElement.parentElement.attributes["_value"].value;
                else if (e._item.parentNode && e._item.parentNode.tagName == "LI")
                    value = e._item.parentNode._value;
                else if (e._item.parentNode && e._item.parentNode.parentNode.tagName == "LI")
                    value = e._item.parentNode.parentNode._value;
                else value = "";
            }
            var searchText = $get('<%=txtWord.ClientID %>').value;
            searchText = searchText.replace('null', '');

            sender.get_element().value = searchText + value;
        }
                                       
   
    </script>
</head>
<body>
    <form id="form1" runat="server">
    <asp:ScriptManager ID="ScriptManager1" runat="server">
    </asp:ScriptManager>
    <div style="text-align: center; margin-top: 200px">
        Search :
        <asp:TextBox ID="txtWord" runat="server" AutoComplete="off" Width="200px" />
    </div>
    <cc1:AutoCompleteExtender runat="server" BehaviorID="AutoCompleteEx" ID="autoComplete1"
        TargetControlID="txtWord" ServicePath="MyService.asmx" ServiceMethod="GetNames"
        MinimumPrefixLength="1" CompletionInterval="1000" EnableCaching="true" CompletionSetCount="20"
        CompletionListCssClass="autocomplete_completionListElement" CompletionListItemCssClass="autocomplete_listItem"
        CompletionListHighlightedItemCssClass="autocomplete_highlightedListItem" OnClientPopulated="acePopulated"
        OnClientItemSelected="aceSelected" DelimiterCharacters=";" ShowOnlyCurrentWordInCompletionListItem="true">
    </cc1:AutoCompleteExtender>
    </form>
</body>
</html>





Result

 

 

Downloads

The source code (with database script in ~/App_Data (around 60,000 records )) can be downloaded below.

AutoCompleteVS2008Sln.zip (4.84 mb)

Enjoy ....

Tags:

.Net | Asp.Net | Tips & Tricks

Best way to parse HTML content

by aboo bolaky 23. September 2009 08:26


I'm going to keep this short and simple..rather short actually.

There is no better way to parse HTML other than using HtmlAgility Pack.

It's a lot simpler than Regex..which is a BIG no no!!

 

Tags:

.Net | Asp.Net | Freebies

Paging and Sorting in a Gridview without using an ObjectDataSource

by Aboo Bolaky 20. November 2008 19:43

Ryan Olshan has created a nice article about Paging and Sorting in a Gridview without using an ObjectDataSource. It's pretty nifty and gives you an insight at you can programmatically do with a GridView.

The article can be viewed here.

Tags:

.Net | Asp.Net

Creating a collapsible HTML List using JQuery

by Aboo Bolaky 17. November 2008 17:19

Yesterday, I came across this really nice article by Jeroen Coumans that explains how to create a collapsible HTML list using JQuery. The reasons why I like his solution are:

1. It's simple and easy to understand. It takes only a couple of lines to write the JQuery code.

2. It allows you to add the "active" CSS class to the selected item in the list.

3. Most importantly, it allows you to have a clickable parent item (where the link to the parent item doesn't just point to a #; it can refer to other pages on your site) 

You can have a look at the article here

 

Tags:

.Net | Asp.Net | Tips & Tricks

FeedBurner and HttpWebRequest Failure

by aboo bolaky 26. September 2008 08:34

 

The other day, I subscribed this blog to FeedBurner . This was all meant to be the way forward Tongue out. What i was trying to do was to use a Web Request to someone's feed url (in my example, http://feeds.feedburner.com/aboobolaky) to gather a few blog entries from the feed (a bit like the blog roll on the left hand side!).

It turns out that the web request fails with a status of "ProtocolError" , with an Exception of "The remote server returned an error: (404) Not Found." . However, if you use an RSS Reader or even point your web browser to the link, it works just fine!! Foot in mouth

Question here..How do we isolate the problem?

  • Is this intentional?
  • Is a proxy server responsible for this?
  • Or, maybe it has something to do with the User Agent?

 

I'll be thinking about this and post an update sooner or later.

In the meantime, I'd better revert my feed url to how it was before

using System;
using System.Configuration;
using System.Data;
using System.Web;
using System.Text;
using System.Net;
using System.IO;
using System.Xml;

public partial class _Default : System.Web.UI.Page
{ 
public class RequestState 
{ 

// This class stores the State of the request. 
const int BUFFER_SIZE = 1024; 
public StringBuilder requestData; 
public byte[] BufferRead; 
public HttpWebRequest Request; 
public HttpWebResponse response; 
public Stream streamResponse; 

	public RequestState() 
	{ 
		BufferRead = new byte[BUFFER_SIZE]; 
		requestData = new StringBuilder(); 
		Request = null; 
		streamResponse = null; 
	} 
} 
protected void Page_Load(object sender, EventArgs e) 
{ 
	HttpWebRequest httpRequest = (HttpWebRequest)WebRequest.Create("http://feeds.feedburner.com/aboobolaky"); 
	RequestState myRequestState = new RequestState(); 
	myRequestState.Request = httpRequest; 
	httpRequest.BeginGetResponse(ProcessResponse, myRequestState); 
} 
private static void ProcessResponse(IAsyncResult async) 
{ 
	RequestState state = (RequestState)async.AsyncState;
	try 
		{ 
			using (HttpWebResponse response = (HttpWebResponse)state.Request.EndGetResponse(async)) 
				{ 
					XmlDocument doc = new XmlDocument(); 
					doc.Load(response.GetResponseStream()); 
					XmlNodeList nodes = doc.SelectNodes("rss/channel/item"); 
					foreach (XmlNode node in nodes) 
					{ 
						string title = node.SelectSingleNode("title").InnerText; 
						/*likewise,list the relevant nodes under /rss/channel/item..*/ 
					} 
				} 
		} 
	catch (System.Net.WebException ex) 
		{
			throw ex; 
		}
} 

} 

Tags: ,

.Net | Asp.Net

Tag cloud

Flash Player 9 required.

About Me

I wish I could write something here..
//TODO: ElaborateMe