Standing on the shoulders of giants. RSS 2.0
Page 1 of 1 in the DevelopmentASPNET category
# Thursday, October 02, 2008

The ‘normal’ use case for using templated databound controls like the listview control is to specify the control and the templates in declarative markup and bind the control in the code-behind.

 <asp:ListView runat="server" ID="listview">
     <LayoutTemplate>
        <ol><li runat="server" id="itemPlaceholder" />ol>
     LayoutTemplate>
     <ItemTemplate>
        <li><%#Eval("item") %>li>
     ItemTemplate>
 asp:ListView>

and in the code-behind:

listview.DataSource = ....
listView.DataBind();

But when you’re building a webpart or a composite control, this is generally not really an option. The way to define templates in the code-behind is to define two classes which implement the ITemplate interface and assign an instance of these classes to the LayoutTemplate and the ItemTemplate properties. (There are a lot more templates you can use, but these are used to show how the concept works.)

The Layout template is the simplest to define:

private class LayoutTemplate : ITemplate
{
    public void InstantiateIn(Control container)
    {
        var ol = new HtmlGenericControl("ol");
        var li = new HtmlGenericControl("li") { ID = "itemPlaceholder" };
        ol.Controls.Add(li);

        container.Controls.Add(ol);
    }
}

The only requirement is that it control with the ID itemPlaceHolder, the listview uses this ID to find the control to replace with the item template when databinding.

The InstantiateIn method in the item template is similar to that method in the layout template: a control is created (the same type as previously) and this is added to the container control, effectively replacing the child-control (with the itemPlaceHolder ID) from the layout template. The only difference is that we register for the databinding event of the childcontrol. In the databinding method a reference to the childcontrol is obtained (the sender parameter) and a reference to the current item from the bound collection.

private class ItemTemplate : ITemplate
{
    public void InstantiateIn(Control container)
    {
        var li = new HtmlGenericControl("li");

        li.DataBinding += DataBinding;
        container.Controls.Add(li);
    }

    public void DataBinding(object sender, EventArgs e)
    {
        var container = (HtmlGenericControl)sender;
        var dataItem = ((ListViewDataItem)container.NamingContainer).DataItem;

        container.Controls.Add( new Literal(){Text = dataItem.ToString() });
    }
}

Complete source: FibonacciControl.txt (1.88 KB)

Thursday, October 02, 2008 12:47:00 AM (W. Europe Daylight Time, UTC+02:00)  #    Comments [0] - Trackback
ASP.NET
# Wednesday, December 27, 2006

 ... or why does your tool introduce bugs in my code and doesn't warn me?

When migrating an ASP.NET 1.1 project to 2.0, using the VS 2005 (SP1) conversion wizard and the Web Application Project conversion tool (included in service pack 1), the AutoEventWireup @page attribute is set to "True" for all pages, even when you previously had set it to "False".

This potentially breaks your application, when you have eventhandlers for init/load/prerender bound manually in places where the conversion tool doesn't change them, e.g. in the constructor of a common basepage. This will cause the events to be handled twice, with unexpected results.

The problem is not that the default is changed from 1.1 to 2.0, but that by modifying my code the tool introduces new (interesting) bugs. And all this without a big neon-sign, which warns for the changes being made and the potential problems it introduces.

Wednesday, December 27, 2006 5:01:17 PM (W. Europe Standard Time, UTC+01:00)  #    Comments [0] - Trackback
ASP.NET
# Wednesday, August 16, 2006

Although there are several ways in ASP.Net to influence the way DateTimes are displayed some methods are better than others and some are evil.

The easiest way to display DateTime and have some influence on them, is to specify the culture and the uiCulture in the globalization tag in the web.config. This is the preferred way if you can use the default date/time formats in that culture.

Example:

<%=DateTime.Now %> is rendered as "16-8-2006 10:14:49" with this globalization tag and rendered as "8/16/2006 10:18:37" with the culture and uiCulture set to en-US.

If you want a little more control, or when the default date/time formats don't offer enough flexibility you can specify a format in the ToString method of the DateTime object. This will still use the culture specified in the web.config for the (abbreviated) names of the months. The downside to this method is that you have to remember to set the correct format string, every time you want to display a date/time.

Example:

<%=DateTime.Now.ToString( "dd MMM \\'yy" )%> is rendered as "16 août '06" with the culture set to fr-FR ( the \\ are required for escaping the ' ).  

 When you want to offer your users a localized version of your web-application, you can't rely on the globalization settings in the web.config, instead you'll have to either set the Culture and UICulture of the current executing thread or use one of the ToString overrides that accepts an IFormatProvider. When you only specify an IFormatProvider, the default (or G) format is used to render the string and although you can override the default format, that is generally considered evil.

Example:

<%=DateTime.Now.ToString( new System.Globalization.CultureInfo("es-ES")) %> is rendered as "16/08/2006 11:43:11", while <%=DateTime.Now.ToString("dd MMM \\'yy", new System.Globalization.CultureInfo("es-ES")) %> is rendered as "16 ago '06".

These methods were the only methods that were available on version 1.x of the .Net framework. In .Net 2.0 you have the ability to define a custom culture using the CultureAndRegionInfoBuilder class. After creating a new culture, this new culture can be installed on a computer and used by any application on that computer. This allows all (web-)applications on that computer to use the same formatting for dates, and numbers, casing etc. This way you can change the default format for string rendering in a less evil way.

Example:

First setup the custom culture using a console application, since this requires administrator rights.

class Program{ 

static void Main( string[] args ) {

if (args.Length == 0 || args[0].EndsWith("i", StringComparison.OrdinalIgnoreCase)) {

RegisterNewRegion();
Console.WriteLine("Registered new region \"x-en-US-custom\".");
} else if (args[0].EndsWith("u", StringComparison.OrdinalIgnoreCase)) {
UnRegisterNewRegion();
Console.WriteLine("Unregistered new region \"x-en-US-custom\".");
} else {
Console.WriteLine("use /i to register and /u for unregister.");
}

Console.WriteLine("Press enter.");
Console.ReadLine();
}

static void RegisterNewRegion() {

// instantiate a new CultureAndRegionInfoBuilder object named x-en-US-demo
CultureAndRegionInfoBuilder cib = new CultureAndRegionInfoBuilder("x-en-US-custom", CultureAndRegionModifiers.None);
//load the culture data from the default en-US culture and region
cib.LoadDataFromCultureInfo(new CultureInfo("en-US"));
cib.LoadDataFromRegionInfo(new RegionInfo("US"));
// set the custom date/time format
cib.GregorianDateTimeFormat.ShortDatePattern = "dd-MM-yy";
cib.GregorianDateTimeFormat.LongDatePattern = "dd MMM \\'yy";
cib.GregorianDateTimeFormat.ShortTimePattern = "HH:mm";
cib.GregorianDateTimeFormat.LongTimePattern = "HH:mm";

// register the culture
cib.Register();
}

static void UnRegisterNewRegion() {

CultureAndRegionInfoBuilder.Unregister("x-en-US-custom");
}

}

Now you can use your custom culture in any web-application, like the previous examples.

<%=DateTime.Now %> is rendered as "16-8-2006 10:14:49" with this globalization tag

Another use would be for writing dates to a log-file, when you need to sort or parse them in future.

Thanks to michkap from Sorting It All Out for the tip on CultureAndRegionInfoBuilder and the post that inspired this post.

Wednesday, August 16, 2006 1:59:42 PM (W. Europe Daylight Time, UTC+02:00)  #    Comments [0] - Trackback
ASP.NET
# Friday, August 12, 2005

System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;

Note: this will be 0.0.0.0 if you use it in the code-forward of an aspx page.

Friday, August 12, 2005 11:54:58 AM (W. Europe Daylight Time, UTC+02:00)  #    Comments [0] - Trackback
ASP.NET | Codesnippet
# Thursday, June 23, 2005

Interesting and annoying behaviour of Asp.Net with respect to HttpModules; the httpModules element in a web.config in a subdirectory, (note: not a seperate application) are ignored. No warning, no error, no nothing, just ignored.

After I spend the better part of yesterday afternoon working on this problem and google wasn’t very helpfull, I hope this will be helpfull to someone.

Proof of concept:

Solution

Layout of the project, notice the second web.config in the subdirectory.

HttpModules element in the root web.config:

<httpModules>

         <add name="FirstHttpModule" type="httpModule.HttpModules.FirstHttpModule, httpModule" />

httpModules>

Interesting part of the FirstHttpModule class

private void context_BeginRequest(object sender, EventArgs e) {
    HttpApplication source = sender as HttpApplication;
    if( source != null ){
        source.Context.Response.Write( "Hello from FirstHttpModule. " );
    }
}

HttpModules element in the subdirectory web.config:

<httpModules>

<clear />

         <add name="SecondHttpModule" type="httpModule.HttpModules.SecondHttpModule, httpModule" />

httpModules>

Interesting part of the SecondHttpModule class:

private void context_BeginRequest(object sender, EventArgs e) {

private void context_BeginRequest(object sender, EventArgs e) {
    HttpApplication source = sender as HttpApplication;
    if( source != null ){
        source.Context.Response.Write( "Hello from SecondHttpModule. " );
    }
}

Result of a request to webform1.aspx in the root:

FirstModule

Result of a request to webform1.aspx in the subdirectory:

SecondModule

 

Source for the proof of concept: httpModule.zip (17.17 KB)
Thursday, June 23, 2005 3:53:41 PM (W. Europe Daylight Time, UTC+02:00)  #    Comments [1] - Trackback
ASP.NET
# Friday, May 20, 2005

Mart is experimenting with WSS 2.0 on windows 2003 R2, he just posted his first article on the installation.

Friday, May 20, 2005 11:24:17 AM (W. Europe Daylight Time, UTC+02:00)  #    Comments [0] - Trackback
ASP.NET | Office 2007
# Thursday, January 27, 2005

Scott Hanselman has a good tip to protect your clients’ clients’ privacy.

This is one a lot of people know, but it's worth covering again because it's easily forgotten as it's a small detail. Since we do eFinance sites, we often don't want folks' UserNames collected and stored in AutoComplete, especially when the site is browsed on a public machine.

autocomplete="off" method="post" runat="server">

Note that autocomplete="false" doesn't work. However, autocomplete="off" works in both IE and FireFox.

Thursday, January 27, 2005 4:55:24 PM (W. Europe Standard Time, UTC+01:00)  #    Comments [2] - Trackback
ASP.NET
# Wednesday, November 17, 2004

Changes have been announced to both the naming of "special" directories (i.e. resources, data, bin ... ) and the compilation model of Asp.net in beta 2 of vs 2005. [0]

Personally I would have preferred a single root for the 'special'-directories, which has been considered, but rejected.

The single root approach was rejected because it did not enable us to support directories located in arbitrary locations in the application tree, such as the local resources directory. 

The default compilation model is changed to keep the markup outside of the compiled binaries. I'm not sure what to think if it, but certainly during development it's a lot easier to work with.

[0] changes in vs 2005 beta 2 for asp.net

Wednesday, November 17, 2004 12:15:37 AM (W. Europe Standard Time, UTC+01:00)  #    Comments [0] - Trackback
ASP.NET | Visual Studio 2005 | Whidbey
About
© Copyright 2009
Paul van Brenk
Sign In
newtelligence dasBlog 2.3.8275.16006
All Content © 2009, Paul van Brenk
DasBlog theme 'Business' created by Christoph De Baene (delarou)