February 2007 - Posts

MIND Community Launching for Vista and Office 2007 Awareness

This was the awareness email that we mail blast to members last week.

http://mind.com.my/blogs/events/archive/2007/02/24/MIND-Community-Launch-for-Windows-Vista-_2600_-2007-Microsoft-Office.aspx

After lunch today we will send out the full agenda list, sponsors and activities to MIND members. Microsoft Malaysia will also be highlighting our event in their other mail blast. Cool!

Thanks.

Posted by chuawenching with no comments

Another compliment by my company's Manager :) Yes

"... and learn something from you. Your motivational level and personal inspirational is high. That has positive energy that others can feel" quote from the email by the manager

I received this email 5 minutes ago from a manager. Basically he works inside our department but I do not work directly with him. Probably through my knowledge sharing, helpings lots of colleagues at office, making things that are impossible to happen :)

Quite suprised though to get compliments from other managers like him.

Thanks so much.

Posted by chuawenching with no comments

ASP.NET 2.0 Page_Load is not a god

Page_Load event is not everything. Use the right page events instead of totaling depending on Page_Load and then blame ASP.NET 2.0 for not being capable J

Giving you an example:

MasterPage

è Default.aspx

o   MultiView

§  View1

·         uclBanking

·         uclInsurance

§  View2

·         uclInsurance

1st user control

No

Bank Name

Account Number

Total

 

2nd user control

No

Insurance

Insurance ID

Total

 

Here is business logic.

1.       Add a new record into 1st user control

No

Bank Name

Account Number

Total

1

SgDotNet

123-123-1213

RM90.00

 

2.       If that new record total is < RM 100.00 it will not populate the total into the 2nd user control.

3.       Now add another new record into the 1st user control

No

Bank Name

Account Number

Total

1

SgDotNet

123-123-1213

RM90.00

2

MIND

321-333-3333

RM150.00

 

4.       By doing this, the value of RM 150.00 will be stored into the 2nd user control GridView. But since you are in the same form you will not see the changes on the fly.

5.       Then how? Most people will click on View2 and back to View1 to see the changes. That is not very good.

6.       Don’t cry. Uncle PreRender to the rescue.

7.       Assuming previously you will check for latest GridView’s DataBind for your 2nd user control Page_Load like this:

 

protected void Page_Load(object sender, EventArgs e)

{

    InvalidateView();

}

 

8.       Change it to this:

 

protected void Page_PreRender(object sender, EventArgs e)

{

    InvalidateView();

}

 

9.       Now give it a try and you see instantaneous updates.

Well I will recommend each of the ASP.NET 2.0 developer to use the right page event. To get started, search in msn live for ASP.NET 2.0 Page Lifecycle. It looks complex but it will come in handy in development.

Posted by chuawenching with no comments
Filed under:

ASP.NET 2.0 Handling Page Refresh / Back from Data Insertion - Not functioning on most scenarios

Remember back then I wrote a blog on this Page Refresh http://community.sgdotnet.org/blogs/chuawenching/archive/2007/02/04/ASP.NET-2.0-Handling-Page-Refresh-_2F00_-Back-from-Data-Insertion.aspx

Honestly speaking, back then it worked fine with normal nonpostback controls except button. But I had not tried it with MultiViews or even the simplest autopostback control like dropdownlist until yesterday.

Unfortunately it didn't work as I had planned. I had tweaked it but failed to get it to work.

Except you choose not to use dropdownlist with the AutoPostBack enabled and MultiView, maybe it will work. Haha.

More researching on this, and hope I can come into a better conclusion with a complex example. Wonder with Microsoft AJAX will solve this issue or not.

Will keep you guys updated.

Posted by chuawenching with no comments
Filed under:

ASP.NET 2.0 Fun Coding #1

Well I named it Fun Coding as I really have no idea what to call it? J

Here is the scenario.

*If you know a better way, let me know.

The project hierarchy:

MasterPage

è Default.aspx

o   uclProgramManagement.ascx

§  MultiView

·         View1

o   uclLogicstics.ascx

o   uclBanking.ascx

·         View2

o   uclInsurance.ascx

Nothing special right J

Assuming each child control (uclLogistics.ascx, uclBanking.ascx and uclInsurance.ascx) has html controls like below:

<%@ Control Language="C#" AutoEventWireup="true" CodeFile="uclBanking.ascx.cs"

    Inherits="uclBanking" %>

<table id="tblMain" summary="This table holds all necessary tables and user controls"

    class="tableGeneral">

    <tr>

        <th>

            <asp:Label ID="lblBankingHeader" runat="server" Text="Banking Information" />

        </th>

    </tr>

    <tr>

        <td>

            <br />

        </td>

    </tr>

    <tr>

        <td>

            <asp:GridView ID="grvBanking" runat="server" SkinID="GeneralView" DataKeyNames="BankingID" AutoGenerateColumns="False">

                <Columns>                   

                    <asp:BoundField DataField="BankingType" HeaderText="Type" SortExpression="BankingType" />

                </Columns>

            </asp:GridView>

        </td>

    </tr>

    <tr>

        <td>

            <br />

        </td>

    </tr>

    <tr>

        <td class="tableRowForButtons">

            <asp:Button ID="btnAddRecord" runat="server" Text="Add Record" SkinID="AddRecordButton"

                OnClick="btnAddRecord_Click" />

        </td>

    </tr>

    <tr>

        <td>

            <br />

        </td>

    </tr>

    <tr>

        <td>

            <table id="tblPanel" class="tableStyle">

                <tr>

                    <td>

                        <asp:Panel ID="pnlInput" runat="server" SkinID="PanelView">

                            <table id="tblInput" class="tableGeneral">

                                <tr>

                                    <td class="tableColumn1">

                                    </td>

                                    <td class="tableColumn2">

                                    </td>

                                    <td class="tableColumn3">

                                    </td>

                                </tr>                               

                                <tr>

                                    <td>

                                        Banking Type <em>is</em>

                                    </td>

                                    <td>

                                        :

                                    </td>

                                    <td>

                                        <asp:DropDownList ID="ddlBankingType" runat="server" AutoPostBack="True" />

                                        <asp:RequiredFieldValidator ID="rfvBanking" runat="server" ErrorMessage="Banking Type is required"

                                            ControlToValidate="ddlBankingType" Display="Dynamic" />

                                    </td>

                                </tr>

                            </table>

                        </asp:Panel>

                    </td>

                </tr>

                <tr>

                    <td>

                        <br />

                    </td>

                </tr>

                <tr>

                    <td class="tableRowForButtons">

                        <asp:Button ID="btnSave" runat="server" Text="Save" SkinID="GenericButton" OnClick="btnSave_Click" />

                        <asp:Button ID="btnReset" CausesValidation="false" runat="server" Text="Reset" SkinID="GenericButton" OnClick="btnReset_Click" />

                        <asp:Button ID="btnClose" CausesValidation="false" runat="server" Text="Close" SkinID="GenericButton" OnClick="btnClose_Click" />

                    </td>

                </tr>

            </table>

        </td>

    </tr>

</table>

Okay from the code above you will notice that I have a panel “pnlInput” which contains the necessary controls to insert new record into the GridView.

Now, visualize this. You will have these 3 user controls in the same web form. Check out the page hierarchy. Taking uclBanking an example. When you click on AddRecord, it will display the “pnlInput” so that you can insert a new record. When you press close, it will hide this “pnlInput”. Same to the other 2 user controls.

So what is the problem here? What if you click AddRecord on all 3 user controls, what will you see?

Definitely all the 3 user control “pnlInput” will be visible. It is nothing wrong about this. Now your customer gives you a call and tells you that when he clicks on the 1st user control’s AddRecords, he expects to see this:

a.       uclBanking “pnlInput” Visible=”True”

b.      uclLogistics “pnlInput” Visible=”False”

c.       uclInsurance “pnlInput” Visible=”False”

This applies to the other user controls.

There are quite a number of ways, but how to maintain less intact among user controls. You can of course do this way:

a.       user control A notifies to user control B to close panel

b.      user control A notifies to user control C to close panel

Looks pretty okay. What if you have 15 user controls? User control A has to speak directly to other 14 user controls. That is a total madness.

So what is a better way?

In my honest opinion, I will do this instead:

Since I have 15 user controls, I will create a parent and child relationships. 1 parent and 15 children.

This parent will act as the publisher and the other 15 will subscribe to this parent.

Let’s get started.

1.       Create a new interface “IPublisher” in App_Code

public interface IPublisher

{

    void Attach(ISubscriber subscriber);

    void Detach(ISubscriber subscriber);

}

2.       Visualize Attach as Adding a new child to the parent. Detach will be the opposite.

3.       Now you need another new interface “ISubscriber” in App_Code

 

public interface ISubscriber

{

    void Update(bool isVisible);

}

 

4.       Now ask yourself why you need an Update method here? For my case each user control needs to have this Update method so you can do necessary callings here. I will actually hide the panel here.

5.       Next, create a new class “ControlCentre” in AppCode. This class will implement IPublisher.

 

using System;

using System.Collections.Generic;

 

public sealed class ControlCentre : IPublisher

{

    List<ISubscriber> subscribers = new List<ISubscriber>();

 

    /// <summary>

    /// Notifies all the subscribers

    /// </summary>

    /// <param name="isVisible"></param>

    public void Notify(bool isVisible)

    {

        // Loop into all the subscribers or user controls

        foreach (ISubscriber subscriber in subscribers)

        {

            subscriber.Update(isVisible);

        }

    }

 

    #region IPublisher Members

 

    /// <summary>

    /// Add to the list of subscribers

    /// </summary>

    /// <param name="subscriber"></param>

    public void Attach(ISubscriber subscriber)

    {

        subscribers.Add(subscriber);

    }

 

    /// <summary>

    /// Remove from list of subscribers

    /// </summary>

    /// <param name="subscriber"></param>

    public void Detach(ISubscriber subscriber)

    {

        subscribers.Remove(subscriber);

    }

 

    #endregion

}

 

6.       Looks straightforward. The thing to take note is the Notify method. Basically assuming you have 15 subscribers, it will loop into all the 15 subscribers and updates all of them.

7.       You need create one last interface “ICallingCentre” in your App_Code.

 

public interface IControlCentre

{

    void NotifyAll(bool isVisible);

}

 

8.       For this interface, you will see the usage later.

9.       Where do you attach these user controls? The page (.aspx) or the parent container (.ascx). The answer is the parent container.

10.   Why? The answer is pretty obvious. Basically you add the 3 user controls into the parent container (.ascx) instead of the page. So this parent container consists the instances of the user controls.

11.   Add this code into your uclProgramManagement.asc

 

public partial class uclProgramManagement: System.Web.UI.UserControl, IControlCentre

{

 

}

 

12.   Make sure it implements IControlCentre interface. Then you need to implement the method in that interface.

 

#region IControlCentre Members

 

public void NotifyAll(bool isVisible)

{

    _dataSource.Notify(isVisible);

}

 

#endregion

 

13.   You need to attach the subscribers in the Page_Load event.

 

private ControlCentre _dataSource;

                

protected void Page_Load(object sender, EventArgs e)

{

    if (!Page.IsPostBack)

    {

       // your code here

    }

 

    _dataSource = new ControlCentre();

    _dataSource.Attach(uclBanking);

    _dataSource.Attach(uclInsurance);

    _dataSource.Attach(uclLogicstics);          

}

 

14.   At this moment I only have 3 user controls. If you have more user controls, just add into the list.

15.   Next, all your user controls need to implement the ISubscriber interface.

 

public partial class uclBanking : System.Web.UI.UserControl, ISubscriber

{ }

 

16.   Then implements the method of the interface

 

#region ISubscriber Members

 

public void Update(bool isVisible)

{

    SetPanelVisibility(isVisible);

}

 

#endregion

 

17.   Now if you click on AddRecord button, you expect it to notify the parent to close all the user controls first before proceeding with other process.

18.   Add this code below for the AddRecord button event.

 

protected void btnAddRecord_Click(object sender, EventArgs e)

{      

    ((IControlCentre)Parent.Parent.Parent).NotifyAll(false);

 

    SetPanelVisibility(true);

}

 

private void SetPanelVisibility(bool isVisible)

{

    pnlInput.Visible = isVisible;

}

 

19.   You will notice that I utilize the IControlCentre to cast the Parent control so I can access the NotifyAll method instead of creating unnecessary instances.

20.   You will be also surprised why I use Parent.Parent.Parent instead of just Parent? I will elaborate as below.

Parent – View

Parent.Parent – MultiView

Parent.Parent.Parent – User Control

21.   So now you know why I choose to do that?

22.   Okay repeat steps 15 – 20 for the other user controls. Give it a try J

Nevertheless every technique has a pro and con.

Pros:

a.       Codes are cleaner and remove dependencies between user controls. Only rely on the ControlCentre to manage this relationship through the usage of IControlCentre.

Cons:

a.       Basically it will close all the panels including the calling User Control

I know this might be basic for a lot of people. But hope someone find this interesting. Do let me know if there is a better way so probably I can improve this. I am in the middle of researching on closing all panels except the calling user control J.

Posted by chuawenching with no comments
Filed under: ,

ASP.NET 2.0 Custom Control Skinning is Possible

Hi,

I will like to apologize on this. If you refer to my earlier blog http://community.sgdotnet.org/blogs/chuawenching/archive/2007/02/16/ASP.NET-2.0-GridView-_2D00_-My-experience-on-skinning.aspx, I mention this "What if I have a custom server control? Can I skin that as well? No you can’t. I had tried this but it didn’t work. If you can get it right, do let me know how?"  Well you can skin a custom user control. I didn't know it can be done this way. Oops. To err is human, to forgive is divine. :)

Check here for more info:

http://weblogs.asp.net/lduveau/archive/2007/02/16/asp-net-2-0-themes-and-custom-controls.aspx

http://odetocode.com/Blogs/scott/archive/2005/09/01/2145.aspx

Anyway I will blog later on my experinece on custom control skinning. Will need to try myself :P

Posted by chuawenching with no comments

ASP.NET 2.0 GridView - My experience on skinning

I will like to share with you my experience on skinning the GridView. Skinning makes your web form so much cleaner. Remember to use skinning and CSS today.

If you are not sure what is a skin, just remember this:

Skin – only for ASP.NET server controls

CSS – for html

So can skin uses CSS? Yes of course, you can. What if I have a custom server control? Can I skin that as well? No you can’t. I had tried this but it didn’t work. If you can get it right, do let me know how?

Again why skin? Then I will ask you again, why use CSS? Hehe. If you never use either one of these, then take this:

Skin/CSS not only makes your codes cleaner but you are able to centralize your control’s display properties in 1 place. So it is easier to manage. Of course over the time, the skin/css file will grow in size. So in order to avoid this, you can compress it or try to avoid using comments inside it. So it makes sure the file size is smaller.

Second personalization. If you notice this is the latest trend for web development. Giving each user an access to customize the look and feel of their site or current space. Or maybe this current blog, I can choose which look and feel I want. If I choose Green, the whole look and feel will be green so is other colors.

Giving you a further example:

<codes>

Okay now back to my original topic. Skinning GridView at first looked easy, but it was not at all. This kept me wondering why? I will explain further below.

Let’s see a simple example below.

Default.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>

 

<!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 runat="server">

    <title>A basic example of skin/css</title>

    <link href="App_Themes/Theme1/StyleSheet.css" rel="stylesheet" type="text/css" />

</head>

<body>

    <form id="form1" runat="server">

        <div>

            <asp:GridView ID="grvFundOwner" CssClass="gridStyle" runat="server" AutoGenerateColumns="False"

                AllowSorting="True" AllowPaging="True" DataSourceID="sdsProduct" DataKeyNames="ProductID">

                <AlternatingRowStyle CssClass="gridAlternatingItem" />

                <HeaderStyle Font-Bold="True" ForeColor="Black" CssClass="gridHeader" />

                <PagerStyle CssClass="gridPager" />

                <Columns>

                    <asp:BoundField DataField="Name" HeaderText="Product Name" SortExpression="Name" />

                    <asp:BoundField DataField="ProductNumber" HeaderText="Product Number" SortExpression="ProductNumber" />

                </Columns>

            </asp:GridView>

            <asp:SqlDataSource ID="sdsProduct" runat="server" ConnectionString="<%$ ConnectionStrings:AdventureWorksConnectionString %>"

                SelectCommand="SELECT ProductID, Name, ProductNumber FROM Production.Product"></asp:SqlDataSource>

        </div>

    </form>

</body>

</html>

 

If you notice in the <head> I have this reference of the CSS file. Let’s see what is inside the CSS file.

StyleSheet.css

 

/* The overall style of the GridView */

.gridStyle

{

      border-color:#A29F9F;  

      border:1;

      width: 100%;

}

 

/* The header of this GridView */

.gridHeader

{

     

      background-color: #BAB9B9 ;

      font-weight:bold;

      color:#000000;         

}

 

/* One row white, another row #E6DACE */

.gridAlternatingItem

{ 

  background-color: #E6DACE;

}

 

/* Paging */

.gridPager

{

     

      background-color:#BAB9B9;

      text-align:right;

}

 

/* Underline the selected page */

.gridPager span

{

      text-decoration: underline;

}

 

Nothing special right. Take note, I will recommend you to use the direct code for color like #BAB9B9 instead of Blue or Red. Previously in Visual Studio .NET 2003 I am using the color naming directly and I have issues with it when I port it over to Visual Studio 2005. I am making an assumption that probably these IDE use different CSS version.

Then you ask why I even need Skin if I can do something like above. If you see properly this code:

<asp:GridView ID="grvFundOwner" CssClass="gridStyle" runat="server" AutoGenerateColumns="False"

                AllowSorting="True" AllowPaging="True" DataSourceID="sdsProduct" DataKeyNames="ProductID">

                <AlternatingRowStyle CssClass="gridAlternatingItem" />

                <HeaderStyle Font-Bold="True" ForeColor="Black" CssClass="gridHeader" />

                <PagerStyle CssClass="gridPager" />

                <Columns>

                    <asp:BoundField DataField="Name" HeaderText="Product Name" SortExpression="Name" />

                    <asp:BoundField DataField="ProductNumber" HeaderText="Product Number" SortExpression="ProductNumber" />

                </Columns>

            </asp:GridView>

Assuming you have 5 of this same GridView in the same web form. It makes the whole page so bulky. The whole point is how to make it so much cleaner?

There is something CSS cannot do, example how do you handle the AlternatingRowStyle, HeadStyle and PagerStyle which are specific to GridView.

Let’s modify our code a bit to support skin.

Before that, I recommend you to create an ASP.NET folder called App_Themes. Inside this App_Themes folder, you create more than 1 themes. So you will be wondering why so many themes? Themes are suitable for personalization. Example you have 4 themes. Each theme represents a holiday celebration in Malaysia. Example:

App_Themes

è ChineseNewYearTheme

è HariRayaTheme

è DeepavaliTheme

è AllCultureTheme

In each Theme folder, you can have 1 skin and 1 css file. Of course you can have more than 1, but I will still recommend you have only 1 skin and 1 css to it is easier for maintenance.

So for this example, create a new skin file called “Controls.skin” under the ChineseNewYearTheme.

<asp:GridView SkinID="GeneralView" CssClass="gridStyle" runat="server" UseAccessibleHeader="False">

    <AlternatingRowStyle CssClass="gridAlternatingItem" />

    <HeaderStyle CssClass="gridHeader" />   

    <PagerStyle CssClass="gridPager" />          

</asp:GridView>

There are 2 important things to note here:

SkinID – you can have this if you want to have specific controls using this Skin or not.

runat=”server” – a must to have

What if you want to have a Skin to apply all the GridView? Simple, just remove SkinID, maybe something like this:

<asp:GridView SkinID="GeneralView" AllowSorting="True" AutoGenerateColumns="False"  AllowPaging="True" CssClass="gridStyle" runat="server" UseAccessibleHeader="False">

    <AlternatingRowStyle CssClass="gridAlternatingItem" />

    <HeaderStyle CssClass="gridHeader" />   

    <PagerStyle CssClass="gridPager" />          

</asp:GridView>

Simple right.

Now update your Default.aspx file. 2 things to note.

a.       Overwrite this code to your existing GridView code.

 

Old

New

<asp:GridView ID="grvFundOwner" CssClass="gridStyle" runat="server" AutoGenerateColumns="False"

                AllowSorting="True" AllowPaging="True" DataSourceID="sdsProduct" DataKeyNames="ProductID">

                <AlternatingRowStyle CssClass="gridAlternatingItem" />

                <HeaderStyle Font-Bold="True" ForeColor="Black" CssClass="gridHeader" />

                <PagerStyle CssClass="gridPager" />

                <Columns>

                    <asp:BoundField DataField="Name" HeaderText="Product Name" SortExpression="Name" />

                    <asp:BoundField DataField="ProductNumber" HeaderText="Product Number" SortExpression="ProductNumber" />

                </Columns>

            </asp:GridView>

 

<asp:GridView ID="grvFundOwner" DataSourceID="sdsProduct" DataKeyNames="ProductID" runat="server" SkinID="GeneralView">

                <Columns>

                    <asp:BoundField DataField="Name" HeaderText="Product Name" SortExpression="Name" />

                    <asp:BoundField DataField="ProductNumber" HeaderText="Product Number" SortExpression="ProductNumber" />

                </Columns>

            </asp:GridView>

 

b.      Add a new attribute at the Page directive

<%@ Page … StylesheetTheme="ChineseNewYearTheme" %>

Try to run your application and there will be the same output. Isn’t that much cleaner?

Then you will wonder, why I don’t put DataSourceID in the skin?

Let’s give it a try.

Update your GridView and skin file to this:

GridView in Default.aspx

<asp:GridView ID="grvFundOwner" DataKeyNames="ProductID" runat="server" SkinID="GeneralView">

                <Columns>

                    <asp:BoundField DataField="Name" HeaderText="Product Name" SortExpression="Name" />

                    <asp:BoundField DataField="ProductNumber" HeaderText="Product Number" SortExpression="ProductNumber" />

                </Columns>

            </asp:GridView>

Controls.skin

<asp:GridView SkinID="GeneralView" DataSourceID="sdsProduct" AllowSorting="True" AutoGenerateColumns="False"  AllowPaging="True" CssClass="gridStyle" runat="server" UseAccessibleHeader="False">

    <AlternatingRowStyle CssClass="gridAlternatingItem" />

    <HeaderStyle CssClass="gridHeader" />   

    <PagerStyle CssClass="gridPager" />          

</asp:GridView>

Try building it, you will get this error:

Error      1              The 'DataSourceID' property of a control type System.Web.UI.WebControls.GridView cannot be applied through a control skin.   C:\Users\chuawenching\Documents\Visual Studio 2005\SkinWebsite\App_Themes\ChineseNewYearTheme\Controls.skin              1             

Error      2              Literal content ('<AlternatingRowStyle CssClass="gridAlternatingItem" />      <HeaderStyle CssClass="gridHeader" />          <PagerStyle CssClass="gridPager" />             </asp:GridView>') is not allowed within a 'skin file'.       C:\Users\chuawenching\Documents\Visual Studio 2005\SkinWebsite\App_Themes\ChineseNewYearTheme\Controls.skin              2                             

Tell yourself why you need Skin and CSS at the first place. Skin and CSS are not meant to do beyond display / layout like DataSourceID.

So if you are new to skin, how can you know which attribute can be used or not? Easy, just trial and error. J

Wait, I have not talk on the advance skinning of this GridView yet. Let’s look further.

Okay what if I want to skin my BoundFields for my GridView. Since I am using a SkinID for each of my GridView, it is possible to skin the BoundFields too.

Let’s review our code again:

Default.aspx

Old

New

<asp:GridView ID="grvFundOwner" DataSourceID="sdsProduct" DataKeyNames="ProductID" runat="server" SkinID="GeneralView">

                <Columns>

                    <asp:BoundField DataField="Name" HeaderText="Product Name" SortExpression="Name" />

                    <asp:BoundField DataField="ProductNumber" HeaderText="Product Number" SortExpression="ProductNumber" />

                </Columns>

            </asp:GridView>

<asp:GridView ID="grvFundOwner" DataSourceID="sdsProduct" DataKeyNames="ProductID" runat="server" SkinID="GeneralView" />

 

Controls.skin

Old

New

<asp:GridView SkinID="GeneralView" AllowSorting="True" AutoGenerateColumns="False"  AllowPaging="True" CssClass="gridStyle" runat="server" UseAccessibleHeader="False">

    <AlternatingRowStyle CssClass="gridAlternatingItem" />

    <HeaderStyle CssClass="gridHeader" />   

    <PagerStyle CssClass="gridPager" />          

</asp:GridView>

 

<asp:GridView SkinID="GeneralView" AllowSorting="True" AutoGenerateColumns="False"  AllowPaging="True" CssClass="gridStyle" runat="server" UseAccessibleHeader="False">

    <AlternatingRowStyle CssClass="gridAlternatingItem" />

    <HeaderStyle CssClass="gridHeader" />   

    <PagerStyle CssClass="gridPager" />

    <Columns>

        <asp:BoundField DataField="Name" HeaderText="Product Name" SortExpression="Name" />

        <asp:BoundField DataField="ProductNumber" HeaderText="Product Number" SortExpression="ProductNumber" />

    </Columns>         

</asp:GridView>

 

1 line of code for the Default.aspx file. Nice. Very clean. Very impressive.

Okay what if I have a new scenario when I need to use TemplateField. How do I skin this TemplateField?

Honestly speaking, I had tested it a lot of times and I couldn’t find a way to skin it. Let’s look in details.

What if I add this piece of code inside my Default.aspx?

Old

New

<asp:GridView ID="grvFundOwner" DataSourceID="sdsProduct" DataKeyNames="ProductID" runat="server" SkinID="GeneralView" />

<asp:GridView ID="grvFundOwner" DataSourceID="sdsProduct" DataKeyNames="ProductID" runat="server" SkinID="GeneralView">

                <Columns>

                    <asp:TemplateField HeaderText="No" HeaderStyle-Width="25px" ItemStyle-Font-Bold="true" ItemStyle-HorizontalAlign="Center">

                        <ItemTemplate>

                            <%                                                                                      RecordNumber++;

                                Response.Write(((grvFundOwner.PageSize * grvFundOwner.PageIndex) + RecordNumber).ToString());

                            %>

                        </ItemTemplate>

                    </asp:TemplateField>

                </Columns>

            </asp:GridView>     

 

 

Nothing special here. Basically what I want to achieve is to place a row number for each records. Okay off topic for a moment, some of them ask me why use this way since SQL Server 2005 already has the row_number feature?

Yes row_number works fine, but when you try to sort your column in the GridView, your rows are not in order anymore. If you know a better way to do this, let me know.

Back to topic.

There are no changes to Controls.skin file. Let’s the output below. Do apologize that I didn’t have time to take screenshot, actually I am suppose to go back to my hometown for holiday, but I feel like sharing this findings to everyone who reads my blog.

Product Name

Product Number

No

Adjustable Race

AR-5381

1

Bearing Ball

BA-8327

2

 

Wait a second. What happen? Why is my No column at the right hand side?

Apparently, the ASP.NET Page will read the BoundFields from the Skin file first before looking at the Default.aspx which is quite obvious to notice right.

I find no ways to solve this.

Now if you look at the TemplateField like below, and how do I skin those HeaderStyle-Width or ItemStyle-Font-Bold?

<asp:TemplateField HeaderText="No" HeaderStyle-Width="25px" ItemStyle-Font-Bold="true" ItemStyle-HorizontalAlign="Center">

                        <ItemTemplate>

                           

                        </ItemTemplate>

                    </asp:TemplateField>

Let’s try this:

<asp:GridView SkinID="GeneralView" AllowSorting="True" AutoGenerateColumns="False"  AllowPaging="True" CssClass="gridStyle" runat="server" UseAccessibleHeader="False">

    <AlternatingRowStyle CssClass="gridAlternatingItem" />

    <HeaderStyle CssClass="gridHeader" />   

    <PagerStyle CssClass="gridPager" />

    <Columns>

        <asp:TemplateField HeaderText="No" HeaderStyle-Width="25px" ItemStyle-Font-Bold="true" ItemStyle-HorizontalAlign="Center" />

        <asp:BoundField DataField="Name" HeaderText="Product Name" SortExpression="Name" />

        <asp:BoundField DataField="ProductNumber" HeaderText="Product Number" SortExpression="ProductNumber" />

    </Columns>         

</asp:GridView>

It looks normal from the code. When you run this, you see as below.

No

Product Name

Product Number

 

 

Adjustable Race

AR-5381

1

 

Bearing Ball

BA-8327

2

 

 

Okay that is funny. It basically adds another new column.

Maybe I should think out of the box and do this in my skin file instead.

Add this new line of code below the skin file.

<asp:TemplateField SkinID="TemplateView" runat="server" HeaderText="No" HeaderStyle-Width="25px" ItemStyle-Font-Bold="true" ItemStyle-HorizontalAlign="Center" />

 

Looking at it does make sense somehow. Basically <asp:TemplateFiled /> looks like an ASP.NET server control. Since skin file only accepts controls with the prefix of <asp: … />

Okay let’s try to add the SkinID in the TemplateField in Default.aspx

<asp:TemplateField>

Sigh. There is no such attribute on SkinID. Probably let me guess Intellisense problem which is common in Visual Studio 2005. I try to add in myself like this:

<asp:TemplateField SkinID="TemplateView">

Let’s build this.

Error      1              Type 'System.Web.UI.WebControls.TemplateField' does not have a public property named 'SkinID'.                C:\Users\chuawenching\Documents\Visual Studio 2005\SkinWebsite\Default.aspx        15          

Error      2              System.Web.UI.WebControls.DataControlFieldCollection must have items of type 'System.Web.UI.WebControls.DataControlField'. 'ItemTemplate' is of type 'System.Web.UI.HtmlControls.HtmlGenericControl'.       C:\Users\chuawenching\Documents\Visual Studio 2005\SkinWebsite\Default.aspx                16          

Okay maybe I can use a generic skin of <asp:TemplateField> without specifying SkinID. Let’s update this in Controls.skin file.

Old

New

<asp:TemplateField SkinID="TemplateView" runat="server" HeaderText="No" HeaderStyle-Width="25px" ItemStyle-Font-Bold="true" ItemStyle-HorizontalAlign="Center" />

 

<asp:TemplateField runat="server" HeaderText="No" HeaderStyle-Width="25px" ItemStyle-Font-Bold="true" ItemStyle-HorizontalAlign="Center" />

 

 

Running this will generate you an error:

Error      1              This object cannot be themed. Only controls of type System.Web.UI.Control are allowed at the top-level of a skin file.            C:\Users\chuawenching\Documents\Visual Studio 2005\SkinWebsite\App_Themes\ChineseNewYearTheme\Controls.skin              11          

Very disappointed at this stage. Why?

a.       My columns are not in order

b.      I can’t skin TemplateField

 

In order to use Skin, you will win something and lose something too:

a.       Partial centralization. Why I will call it partial? If you see the explanation above, TemplateField is not supported. So you cannot centralize everything in skin field.

b.      Based on my findings, I will recommend you to place your columns inside the Default.aspx file instead of placing it in skin file. Then have a generic GridView without the SkinID which you can apply to all your GridViews within this Theme “ChineseNewYearTheme”. The reason I say this as most of the time all of our data display tables are using the same coloring and layout standard. You seldom find a page with 5 GridViews with different colors. That is bad design.

c.       Start using Skin and CSS file. Probably this will improve in the next generation of ASP.NET, will keep my fingers crossed.

Lastly, Skin and CSS are ways to make your controls and page cleaners. You can apply skins on web form using Master Pages. No much hassles.

Hope you like my findings.

Posted by chuawenching with 4 comment(s)
Filed under: , ,

Happy Chinese New Year and Happy Holidays

Dear all (my blog readers, MIND, INETA, Microsoft, SgDotNet, other communities, best friends, friends, friendster friends, family, relatives, non stop list),

  I will like to wish you a Happy Chinese New Year and a Happy Holiday for those who don't celebrate Chinese New Year. I will not be around till next Thursday, so probably my blog will be empty within this period.

  I am going back to my hometown Muar, Johor this afternoon.

  Thank you.

Cheers.

Posted by chuawenching with no comments

ASP.NET 2.0 - Achieving blending between pages. Partial eliminate flickering

Thanks Hannes. He shown me a good tip today about page blending and it did remove flickering.

So how can you do this? Easy, just paste this code below in your web form or master page header.

<meta http-equiv="Page-Enter" content="blendTrans(Duration=1.0)">
<meta http-equiv="Page-Exit" content="blendTrans(Duration=1.0)">

At the moment I am placing 1 seconds as the duration which is okay. I will recommend not to put more than 1 second.

Just to make sure there is no problem with my site, I have tested with debugging. Just in case who knows that code causes debugging to fail. Things work great.

Probably for now before April, I will stick to this page blending. However I will like to leverage AJAX. 2 reasons - develop better web application for the customers and support Microsoft Technologies in my company as well as share it to the community.

Posted by chuawenching with no comments

Vista Developer Nightmare #4 - Where is my ASPNET Worker Process?

In Windows XP, you can see aspnet_wp worker process. In Windows Server 2003, you can see w3wp worker process. But not in Windows Vista. Weird.

I am not sure in details yet, but probably will read out some documentation from IIS 7.

Posted by chuawenching with no comments

Vista Developer Nightmare #3 - Unable to debug Web Application on Visual Studio 2005

It freaked me out at first. Take note, for those who migrate web applications running on the older IIS 5.1 / 6, when you create a new application in IIS 7 make sure you change from DefaultAppPool to Classic .NET AppPool.

Posted by chuawenching with 1 comment(s)

ASP.NET 2.0 GridView - ObjectDataSource versus Custom Binding

I had done a number of researches lately on whether should I use ObjectDataSource which comes out of the box from Microsoft ASP.NET 2.0. Previously, we had done manually using custom binding.

I still remember back then somewhere in my blog, William asked me to measure between complexity and performance. Doing too much custom codes make things so complicated and hard to handle. This is what I believe now?

If I use custom binding it will take me extra 2 hours to finish off something unlike ObjectDataSource.

As you see if you use ObjectDataSource to handle the communication between the presentation layer (which is your GridView) and Business Layer (custom objects or you can use DataSet), you will have a so much cleaner presentation layer. Unlike my previous codes, I do all the manual binding at the presentation layer it makes the whole codes so messy. Of course you can introduce design patterns like M-V-P to handle the separation of presentation layer.

There are a number of articles written by ScottGu and Scott Michell on enabling efficient paging/sorting using ObjectDataSource. I personally had tested it at my project now.

So I will conclude now:

a.       Use ObjectDataSource and try to prevent complexity. Don’t get me wrong. Separation of User Interface matters. But do keep your presentation as clean as possible. What if you have a graphic designer doing the front end for you, do they have to care with all this bindings? But you still have to write some codes when using ObjectDataSource. J

b.      If you complain about performance with ObjectDataSource, then read the articles by the ScottGu and Scott Michell. Basically if you noticed in their articles, they leveraged 2 things – row_number a feature in SQL Server 2005 and passing back 10 rows of records each time instead of the whole table (assuming you have 10000 rows). Previously we got the 10,000 rows and filter 10 rows on the User Interface’s side. Honestly speaking it is not wrong but not a really recommended approach. It is so slow. So I assume it has nothing to do with ObjectDataSource but more to how you write your ASP.NET and Stored Procedures.

c.       There are a number of drawbacks for ObjectDataSource but no data control is perfect. If it is designed to be so generic or multipurpose, it is better they provide the API and we as developer code it ourselves.

d.      The thing you will like about ObjectDataSource is the support for optimistic concurrencies either last win approach or comparing each field. Well I think it is great. However, I have a better way to handling this situation by comparing timestamp. Like I said, if you do the timestamp there will be extra steps and you have to weight against complexity and performance. Just in case you are not sure what is optimistic concurrency is if both users access the same record and one updates it first, will the other user be notify on the changes.

 

Remember, customers care about deliveries first and performance/security/misc second. If you can’t deliver the business functionalities, there is no point. However, you still encouraged to the do things right. Let me know what you guys think. J

Posted by chuawenching with 2 comment(s)

Nando's lunch - broke the plate hanged on the wall ... Oops

For the ISA briefing last Monday was a successful one. My boss treated us lunch in Nando. Well I did mentioned this in my earlier post. However there was something new earlier today.

While joking with my colleagues and leaning against the wall of the Nando's Subang Parade restaurant , I accidentally broke the plate hanged on the wall. Oops.

Hope it was not a bad sign. Lucky I am still single so it is not a bad sign that I will get ditched during Valentines Day. :P

It looked expensive though. Haha. I pretend nothing happen. Shhhh...

Posted by chuawenching with no comments

MIND Vista and Office 2007 Launching - probably the greatest MIND event ever

MIND will have our Vista and Office 2007 community launching on March 3rd, 2007. I have not announce it yet officially as we are working on the details. But I will blog a rough overview of the session.

This event could be the biggest for MIND since I took up this role as the president of the community. Microsoft Malaysia is expecting a crowd of 100 people but I am aiming it for 300 people.

I can't guarantee that I can hit that target but who knows. Never try never knows.

I am aiming for a 2 tracks events using 2 auditoriums. 1 auditorium can fit approximately 150 people. Both of these auditoriums are in Microsoft Malaysia.

There will be 12 speakers for this event, 6 for Vista and 6 for Office 2007 development related. There will be no speakers from Microsoft Malaysia and all of them are from the industry. Minimum 3 years of working experiences and more preferred. Second, I will welcome my members to participate for this event. One had volunteered. Great :)

However Microsoft Malaysia will supporting us for this event. Thanks to them so much.

At this moment, I had already obtained sponsors 11 -12 around the world. I will not mention the names yet as it is still secret. :) Thanks to the sponsors and for those who believe in me. More sponsors to come. Can't wait.

If I able to get the speakers and a lot of sponsors, I will get TheStar In-Tech to cover the story. Not sure this is going to happen. Let's see how things go?

There will also a hidden agenda for this event. Probably this hidden agenda is the one going to draw the crowd. Basically you will guess what I mean ...hint... sponsors and goodies :P The top 2 goodies cost 4 digits. Hehe.

For this event launching, one of the sponsors will be designing our event's web graphics and posters. I had seen their conceptual art and it was indeed amazing. Kudos to that sponsor. Probably this is the 1st time people designing graphics for my event. Actually I helped the CEO of that company a lot in the past, probably he is helping me out this time. Thanks man.

That is all for now. Keeping my fingers crossed for this event.

Posted by chuawenching with no comments
More Posts Next page »