Ryan Ternier

Killer ASP.NET ninja coding monkeys do exist!

April 2006 - Posts

How to Generate Roman Numerals

One thing you get when you work with a customer base as wide as the one we have at our company is a list of useful scripts. As no two customers want the exact same thing, these little scripts come in handy.

Here is one that I have that changes an Integer into a Roman Numeral.

Let's show some code first:

private string ConvertToRoman(int Value)
        {
            System.Text.StringBuilder sbRN = new System.Text.StringBuilder();

           
            //Start high, and just replace the huge numbers with letters.

            // 1111 -> M111 -> MC11 ->MCX1 -> MCXI
            sbRN.Append(GenerateNumber(ref Value, 1000, 'M'));
            sbRN.Append(GenerateNumber(ref Value, 500, 'D'));
            sbRN.Append(GenerateNumber(ref Value, 100, 'C'));
            sbRN.Append(GenerateNumber(ref Value, 50, 'L'));
            sbRN.Append(GenerateNumber(ref Value, 10, 'X'));
            sbRN.Append(GenerateNumber(ref Value, 5, 'V'));
            sbRN.Append(GenerateNumber(ref Value, 1, 'I'));

            //let's replace the some substrings like:
            //IIII to IV, VIV to IX, etc.

            sbRN.Replace("IIII", "IV");
            sbRN.Replace("VIV", "IX");
            sbRN.Replace("XXXX", "XL");
            sbRN.Replace("LXL", "XC");
            sbRN.Replace("CCCC", "CD");
            sbRN.Replace("DCD", "CM");
            return (sbRN.ToString());
        }

        private string GenerateNumber(ref int value, int magnitude, char letter)
        {
            System.Text.StringBuilder sbNumberString = new System.Text.StringBuilder();

            while (value >= magnitude)
            {
                value -= magnitude;
                sbNumberString.Append(letter);
            }
            return (sbNumberString.ToString());
        }

 

Roman Numerals are pretty straight forward once you get used to it. When you start with a number, say 1234, you will want the roman numeral: MCCXXXIV.

What this above script will do is take in the 1000, set M  to the letter to be returned, and take 1000 off of the Value (Passed by Reference). It will then take the 200 and return CC, the 30 return XXX and the 4 which will return IIII. The IIII is then turned into IV.

Pretty easy script to use, and helpful if you ever need to produce Roman Numerals.


Posted: Apr 26 2006, 01:13 PM by Ryan Ternier | with 1 comment(s)
Filed under: ,
Manipulating Data in a Repeater Control

After browsing some of the posts on the asp.net forums a few people asked how to manipulate data in a Repeater Control. Here is a quick sample on how to do this.

A repeater is very powerful tool when you need to well... repeat something many times. If you are going to be repeating tabular data, use a DataGrid, for anything else use a Repeater.

First, A few notes on the Repeater:

The Repeater control allows you to create templates to define the layout of its content. The templates are:

 

  • ItemTemplate - Use this template for elements that are rendered once per row of data.
  • AlternatingItemTemplate- Use this template for elements that are rendered every other row of data. This allows you to alternate background colors, for example.
  • HeaderTemplate- Use this template for elements that you want to render once before your ItemTemplate section.
  • FooterTemplate- Use this template for elements that you want to render once after your ItemTemplate section.
  • SeperatorTemplate- Use this template for elements to render between each row, such as line breaks.

After a repeater has been created, you might end up with something like this:

<asp:Repeater ID="rptApprovesr" runat="server" OnItemCommand="rptApprovesr_ItemCommand">

    <HeaderTemplate>

        <table border="0" cellpadding="0" cellspacing="0">

    </HeaderTemplate>

    <ItemTemplate>

        <tr>

            <td>

                <asp:ImageButton ID="imbDelete" CommandName="Delete" runat="server" ImageUrl="~/Images/button_delete.gif" /><td>

                    <asp:Literal ID="litStaffID" runat="server" Text='<%#DataBinder.Eval(Container.DataItem,"StaffID") %>' Visible="false" />

                    <asp:Literal ID="litApproverName" runat="server" Text='<%# DataBinder.Eval(Container.DataItem,"FullName") %>' /></td>

                <td>

                    <asp:ImageButton ID="imbMoveDown" CommandName="MoveUp" runat="server" ImageUrl="~/Images/button_Up.gif" /><td>

                    <asp:ImageButton ID="imbMoveUp" CommandName="MoveDown" runat="server" ImageUrl="~/Images/button_down.gif" /><td>

        </tr>

    </ItemTemplate>

    <FooterTemplate>

        </table></FooterTemplate>

</asp:Repeater>

Now that we have a repeater, we might want to manipulate some Data. We can use front end binding like you see above: Text='<%# DataBinder.Eval(Container.DataItem,"FullName") %>' or we can use the ItemDataBound event:

protected void rptApprovesr_ItemDataBound(object sender, RepeaterItemEventArgs e)

{

    if(e.Item.DataItem != null)

    {

        //Change a the staff ID to 1.

        ((Literal)e.Item.FindControl("litStaffID")).Text = "1";

        //Add the Approver Name

        ((Literal)e.Item.FindControl("litApproverName")).Text = ((((System.Data.DataRow)e.Item.DataItem)["ApproverName"]).ToString());

    }

}

The ItemDataBound event is called for each "row" you are adding to the repeater. If your DataSource has 10 rows, this function will be called 11 times (the first time doesn't have a valid DataItem that's why I do the check at the front). You can see above that I can use the FindControl method with the actual control ID passed in to access that control.

I can also declare a control and manipulate it that way If I needed to do more than just change the text:

        ImageButton imgDelete = (ImageButton)e.Item.FindControl("imbDelete");

        imgDelete.CssClass = "Some Style Class";

        imgDelete.AlternateText = "Delete something";

        imgDelete.CommandName = "Delete";

When you do the above, you are creating a pointer reference to the actual object in the repeater. In other words you don't need to "Re-Add" the control to the repeater. Any changes you do to it will automatically be reflected to the current item (row) of the repeater.

Posted: Apr 07 2006, 01:12 PM by Ryan Ternier | with no comments
Filed under: ,
Handling autopostbacks within a repeater - Checkbox Style

An issue I had today stumped me for awhile. I had a repeater, and inside it I had a checkbox. When the checkbox was updated (checked / unchecked) I needed it to postback to the server. I found a solution.  Here's my Repeater layout:

<asp:Repeater ID="rptApprovers" runat="server">

    <HeaderTemplate><table></HeaderTemplate>

    <ItemTemplate>

        <tr>

            <td style="width:180px;">

                <asp:Literal ID="litStaffID" Text='<%#DataBinder.Eval(Container.DataItem,"StaffID") %>' runat="server" />

                <asp:Literal ID="litStaffName" Text='<%#DataBinder.Eval(Container.DataItem,"FullName") %>' runat="server" />

            </td>

            <td style="width:100px;">

                <asp:CheckBox ID="chkApproved"  Checked='<%#  Boolean.Parse(DataBinder.Eval(Container.DataItem,"Approved").ToString()) %>' OnCheckedChanged="chkApproved_CheckChanged" Text="Approved" runat="server" AutoPostBack="true" />

            </td>

        </tr>

    </ItemTemplate>

    <FooterTemplate></table></FooterTemplate>

</asp:Repeater>

What I needed was when clicking a checkbox, was for it to postback and update my Database.
Seeing the repeater does not have a way of tracking autopostbacks that happen from controls within the repeater, I had to do this within the checkboxes OnCheckChanged event:
 

To accomplish this I needed to do the following code: 
CheckBox chkBox = (CheckBox)sender;		
RepeaterItem riContainer = (RepeaterItem)chkBox.NamingContainer;		
int intStaffID;		
//Get the StaffID to update		
intStaffID = Int32.Parse(((Literal)riContainer.FindControl("litStaffID")).Text);
//Update the DataBase
 
I've never used the NamingContainer property before, and in this case it has turned out to be quite helpful.
Posted: Apr 04 2006, 01:11 PM by Ryan Ternier | with no comments
Filed under: ,
More Posts