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>