Tuesday, December 1, 2009

Proper Case Function in C#

I found this proper case function but had no way to comment on how to improve it so I will post it in my blog. There are times when you want to capitalize words with hyphens such as capitalizing the S in Ann-Smith. I modified the function as follows:


public static string ProperCase(string stringInput)

{

    System.Text.StringBuilder sb = new System.Text.StringBuilder();
    bool fEmptyBefore = true;
    foreach (char ch in stringInput)

    {

        char chThis = ch;
        if (Char.IsWhiteSpace(chThis))
            fEmptyBefore = true;
        else if (Char.IsPunctuation(chThis))
            fEmptyBefore = true; // treat punctuations as spaces
        else
        {
            if (Char.IsLetter(chThis) && fEmptyBefore)
                chThis = Char.ToUpper(chThis);
            else
                chThis = Char.ToLower(chThis);
            fEmptyBefore = false;
        }
        sb.Append(chThis);
    }
    return sb.ToString();

} 


As you can see, the section with the comment "treat punctuations as spaces" was added to handle these situations.

Other Possible Improvements: Handling words such as McDonald.


Adiel

Thursday, November 5, 2009

Data Structures and Algorithms blog

I have created a new blog. The purpose of this new blog is to convert samples from the classic book Data Structures and Algorithms.

Adiel

Thursday, February 26, 2009

Referencing a web control inside a formview from client-side javascript

A quick tip. If you need to reference a web control in a client-side javascript, you would normally do something like this:

<script type="text/javascript" language="javascript">
    function setupMyCheckBox()
        {
            var chkMyCheckBox = document.getElementById('<%=chkMyCheckBox.ClientID%>');
            //...do something with the object here
...


But if the field is inside a formview for example, this is how you would reference it:

<script type="text/javascript" language="javascript">
    function setupMyCheckBox()
        {
            var chkMyCheckBox = document.getElementById('<%=frvMyForm.FindControl("chkMyCheckBox").ClientID%>');
            //...do something with the object here
...

One thing to keep in mind. If you have different formview or gridview modes. (such as view, edit and insert). Then you must setup a "dummy hidden control" in each mode's section in order to avoid an object not found error in the javascript code. You can set it to be a literal or if you are referencing it in code-behind, set it to be the same type as the original field but hidden. Here is an example when setting it as a literal. Note this field has no use except to avoid an error when running the FindControl method in the javascript.

<asp:Literal ID="chkMyCheckBox" runat="server" Visible="false">asp:Literal>

Thursday, February 19, 2009

Joining two DataTables

Lets say you just brought back some data from a query and you want to rearrange the data or you simply have two datatables with the same schema that you want to join. Here is some sample code that will place the main customer first and then the additional customers sorted by customerId:


// Customers Object
clsCustomers objCustomers = new clsCustomers();

// Get Main Customer ID and Customer DataSet
int customerId = objCustomers.getMainCustomer();
DataSet dsCustomers = objCustomers.getCustomers();

// Create Temp Table to hold Main/Additional Customers sorted with Main Customer First
DataTable dtTempTable = new DataTable();

// Create Temp View to hold Main/Additional Customers
DataView dvCustomer;

// Setup Main Customer using RowFilter
dvCustomer = dsCustomers.Tables["Default"].DefaultView;
dvCustomer.RowFilter = "customerId = '" + customerId + "'";

// Add Main Customer to Temp Table
// The ToTable method is used to copy just the results of the RowFilter
dtTempTable = dvCustomer.ToTable();

// Setup Additional Customers using RowFilter and Sorting
dvCustomer = dsCustomers.Tables["Default"].DefaultView;
dvCustomer.RowFilter = "customerId <> '" + customerId + "'";
dvCustomer.Sort = "customerId";

// Add Additional Customers to Temp Table
// The Merge method is used to merge the two tables together
dtTempTable.Merge(dvCustomer.ToTable(), false, MissingSchemaAction.Add);

All Done! Now you have your DataTable dtTempTable sorted with the main customer first and then the rest of the customers sorted by customerId.

Wednesday, February 4, 2009

FormView, User Controls and Events

Lets say you have a webform (aspx) with a formview that has a user control inside. How would you handle an event from the user control in your webform?

Since the user control is inside the formview, you cannot just place the code in the OnInit method like you might do for events that are part of your web form:

        protected override void OnInit(EventArgs e)
        {
 
            // First call the base oninit
            base.OnInit(e);
 
            // Add Event Handler for new request created - This will not work:
            usrMyControl1.CustomerCreated += new EventHandler(CustomerCreated);
        }


The reason being that the control has not been created yet. It will be created later on when you bind your FormView. So, the correct place to create the handler is in the ItemCreated method of the FormView :

        protected void frvCustomers_ItemCreated(object sender, EventArgs e)
        {
            // When handling an event of a user control inside a formview, you must add 
            // the event handling inside the ItemCreated method
            usrMyControl usrMyControl1 = (usrMyControl)frvCustomers.FindControl("usrMyControl1");
            usrMyControl1.CustomerCreated += new EventHandler(CustomerCreated);
        }

We now know the proper place to create the handler. But, you might not need to create a handler. If you only want to handle lets say an ok button pressed on the user control, you can simply use the fact that on a postback the PreRender method is called and no need to create or handle the above event!

        protected void frvCustomers_PreRender(object sender, EventArgs e)
        {
 
            try
            {


// Here you can create an instance of the user control
// then you can get its properties and use those properties
// in your webform for example to change the value of a textbox

                // Reference the objects from the FormView
                TextBox txtFirstName = (TextBox)frvCustomers.FindControl("txtFirstName");
 
 
                // Access User Control if the ok button was pressed (objCustomerPicker object exists)
                usrMyControl usrMyControl1 = (usrMyControl)frvCustomers.FindControl("usrMyControl1");
                if (usrMyControl1.objCustomerPicker != null)
                {
// Set FormView data from user control
                    clsCustomerPicker objCustomerPicker = usrMyControl1.objCustomerPicker;
                    txtFirstName.Text = objCustomerPicker.firstName;
                }
 
            }
 
            catch (Exception ex)
            {
                lblStatus.Text = "ERROR: frvCustomers_PreRender: " + ex.Message;
            }
 
        }


The clsCustomerPicker class is just a Serializable class that contains the properties of the user control:

[Serializable()]
    public class clsCustomerPicker 
    {
 
        // Public Variables 
        public string country;
        public string firstName;
        public string lastName;
        public string cellphone;
 
    } 


Basically following the above example of clicking on a button. You would have a method in your user control that handles the ok button, instantiates the above class and sets the values of the class such as country, firstname, etc. I also save the values to viewstate after to access them from the web form during pre_render of the formview:

                // Save Object in viewstate, you would place this in the function
// handling the submit of the button inside the user control
                ViewState["objCustomerPicker "] = objCustomerPicker;


Finally you set up the method to get the values of the class in viewstate:

        public clsCustomerPicker objCustomerPicker 
        {
            get
            {
                // Send Back Value
                if (ViewState["objCustomerPicker"] != null)
                    return (clsCustomerPicker )ViewState[" objCustomerPicker"];
                else
                    return null;
            }
        }



And thats all. You now have seen a couple of options on how to handle data inside a formview which uses a user control.

Tuesday, January 20, 2009

Lazy load a .Net TabContainer's TabPanel

In order to increase performance on the ASP.Net TabContainer, it is a good idea to lazy load the tabs. As of February 2009, the ASP.NET Ajax Toolkit TabContainer does not have this support. However thanks to Matt Berseth, we have a very useful article on how to lazy load a tabcontainer's tabpanels. Since the article is already very informative, I will not rewrite it here. However, I wanted to expand on the article: how to use it for user controls within a tabpanel. Here are the steps:

1. Follow the guidelines in the article.
2. Add the user controls to each tabpanel. You will see Matt's original example for the updatepanel inside the tabpanel is for grids:


   12         <asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional">

   13             <Triggers>

   14                 <asp:AsyncPostBackTrigger ControlID="btnCustomersTrigger" />

   15             </Triggers>

   16             <ContentTemplate>

   17                 <asp:GridView ID="gvOrders" runat="server" />

   18             </ContentTemplate>

   19         </asp:UpdatePanel>



In our case, we want to lazy load a user control instead of a grid. The update panel will be as follows:


   49         <asp:UpdatePanel ID="uppCustomers" runat="server" UpdateMode="Conditional" Visible="false">

   50             <Triggers>

   51                 <asp:AsyncPostBackTrigger ControlID="btnCustomersTrigger" />

   52             </Triggers>

   53             <ContentTemplate>

   54                 <uc1:usrcustomers id="usrCustomers1" runat="server"></uc1:usrcustomers>

   55             </ContentTemplate>

   56         </asp:UpdatePanel>



Notice the code changes. We now have a user control called usrcustomers inside the uppcustomers updatepanel instead of gridview control. Marking the panel hidden (visible="false") will remove the update panel div tags completely from the code. With user controls, this will be the way we check if the panel has already been loaded. This takes us to step 3.

3. Modify the clientActiveTabChanged function as follows. This is Matt's original client side javascript function for lazy loading gridviews as part of a partial postback:


    8 

    9     <script type="text/javascript" language="javascript">

   10 

   11         function clientActiveTabChanged(sender, args) {

   12 

   13             //  see if the table elements for the grids exist yet

   14             var isTab1Loaded = $get('<%= this.gvOrders.ClientID %>');

   15             var isTab2Loaded = $get('<%= this.gvEmployees.ClientID %>');

   16 

   17             //  if the tab does not exist and it is the active tab, 

   18             //  trigger the async-postback

   19             if (!isTab1Loaded && sender.get_activeTabIndex() == 1) {

   20                 // load tab1

   21                 __doPostBack('btnCustomersTrigger', '');

   22             }

   23             else if (!isTab2Loaded && sender.get_activeTabIndex() == 2) {

   24                 // load tab2

   25                 __doPostBack('btnEmployeesTrigger', '');

   26             }

   27         }

   28     </script>





Here is the modified version. We will now check if the tab has loaded by update panel visibility instead of gridview table status:


    9     <script type="text/javascript" language="javascript">

   10 

   11         function clientActiveTabChanged(sender, args) {

   12 

   13             // see if the objects exist yet

   14             var isTab1Loaded = $get('<%= this.uppCustomers.ClientID %>');

   15             var isTab2Loaded = $get('<%= this.uppProducts.ClientID %>');

   16 

   17 

   18             // if the tab does not exist and it is the active tab,

   19             // trigger the async-postback

   20             if (!isTab1Loaded && sender.get_activeTabIndex() == 1) {

   21                 // load tab1

   22                 __doPostBack('<%= this.btnCustomersTrigger.UniqueID %>', '');

   23             }

   24             else if (!isTab2Loaded && sender.get_activeTabIndex() == 2) {

   25                 // load tab2

   26                 __doPostBack('<%= this.btnProductsTrigger.UniqueID %>', '');

   27             }

   28 

   29         }

   30     </script>



Again, notice the changes, the code is now checking for the existence of the update panel instead of a gridview. Also the postback code now uses UniqueID to make sure we find the correct buttons.

4. Handle the hidden button events from the partial postback. As Matt points out in his article, create the buttons for the postback as follows:


   36         <input id="btnCustomersTrigger" runat="server" type="button" style="display:none" onserverclick="btnCustomersTrigger_Click" />


Setting up the buttons will be the same for user controls. You will need to setup one button per TabPanel. The only difference is when you handle the button click event:


   15     protected void btnCustomersTrigger_Click(object sender, EventArgs e)

   16     {

   17         // Mark the update panel as visible

   18         uppCustomers.Visible = true; //this is how we will know tab is loaded

   19         // Setup Customers User Control

   20         usrCustomers1.customerId = customerId;

   21         usrCustomers1.initCustomer(); //here you could be doing custom sql calls

   22         //setting up a formview, etc

   23     }




In this function you first mark the update panel as visible. This will tell our javascript function clientActiveTabChanged that the control/tab has already been loaded and not try to reload the tab again the second time it is selected. Finally you would call methods/properties from your user control to setup the details of the user control.

One thing to keep in mind is when you the above technique, the form_load event for all the user controls in all the tabs will still execute when the tabcontainer control is first loaded and on the first time any tab is clicked. Having this in mind, make sure you are not setting up your user control from the form_load event, rather create a method such as initCustomer mentioned in the above example. Hopefully we will not have to do all this extra work once Microsoft changes the tabcontainer control to only load the active tab on a partial postback.

Adiel

Welcome to the Nifty Programming Blog

This blog will cover such topics as Programing Techniques, Systems Analysis, .NET Development and the Systems Development Life Cycle (SDLC) in general. I hope the information will be of benefit to many. Enjoy...

Adiel