CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Eric Wise

Business & .NET

July 2005 - Posts

  • IE 7.0 Beta

    For the most part, I like it. Next version though can I please put the file menu up top where it belongs?
  • Rich ASP .NET Applications

    Peter blogs about why not to focus on building richness into your web applications.  I'd like to go on record that I both agree and disagree with him.

    Know Your Audience

    Are you building an inward-facing application where all the user's hardware is known and everyone is using the same version of a browser?  This is the perfect situation in which to build as much richness as the users desire into the application!  Outward facing applications can be rich as well, but it does depend on your audience.  If you are serving a known community, like a customer portal, then you can legitimately recommend certain browsers for use in your site.  The more public and anonymous your users get the more you have to back away from richness.

    Relative Sizes

    Once again, know your audience.  If you're aiming at the general internet you had best make sure that your site behaves nicely on 800x600 resolution.  Also try to anticipate the relative bandwidth users have.  Obviously in the more general internet there are many users still on dialup connections and we don't want to give them a user experience laden with graphics and flash that take a long time to load.

    Drilling Down

    For the most part this is fine, but try to come up with a navigation system that can accomodate people who know where they are going and want to jump directly to it.  I definitely agree with not cramming many different functions onto a single webpage.  This can cause information overload in a lot of users.  I try to follow the rule of thumb of one page, one purpose.

    Context Menus Are Evil

    I've never been able to get the average joe blow user to "get" context menus.  Putting context menus in your application is just like begging for more calls to the help desk.  In addition, on sites that are more public facing an older browser may not know how to render the context menu and then suddenly you have a user that can not access the functionality.  In this case you have to detect the browser and render the menu items on the page anyway.  I just feel this is way more trouble than it's worth.

  • PrettyCode .Print

    Recently I was tasks with some of the other senior developers at my employer to come up with a code review system.  I'd been pushing for this for a while since the company previously did very little in the way of formal code reviews.  Way back when in my vb 6.0 days the team I was on used to use a program called PrettyCode.Print to nicely format our code for printing code for use in reviews and handouts.

    I really liked this product back in the day, so I decided to see if they had a .NET version.  They do!  The things I really liked about this program were:

    1. Easy checkbox selection so you only print the code sections you want.  It groups things by module, class, namespace, and member.
    2. Connects code blocks with lines.  This is great when you have chains of conditional logic or loops within eachother.  The lines let you easily see where each block ends.

    Anyway, I'll be blogging about our process sometime soon.  Here's a link to pretty code if you want to peek at it.  http://www.submain.com/?nav=products.pcp.net

  • Dropdownlist Autopostback in a Datagrid EditItemTemplate

    Here's a fun one I did for the IAmBrilliant project.  There are several places in the system where there is entering and editing of address information.  So we wanted to come up with a nice little user control that could be shared across pages.  (You can download the source page here since community server is a pain in the ass about displaying html tags)

    So as you can see from the source page we have a datagrid with a variety of template columns that allows editing existing rows and adding new items in the footer.  The template columns are also used to format the addresses nicely.

    Two things I'd like to draw your attention to is the state and county dropdownlists.  It was a user requirement that the state be bound from the database and that when you select a state it populates the county dropdowns with all the counties for that state.  Of course this also introduces the complexity on edit of not only handling the postback gracefully, but setting the selected index of the dropdown list.

    Step 1: Populating the state list

    Looking at the html file you'll see that we are using a function in the codebehind file to populate the state dropdown- Datasource='<%# GetStates() %>'

    The concept that you can set properties on your objects by calling a codebehind function is a pretty powerful one.  All you have to do is declare the method being called as protected or public and then the page can access them.  I am using my RAD Pattern in this application, so the GetStates() method is as simple as this:

        Protected Function GetStates() As DataTable
            _states = Me.GetDomainManager.ListSummary(New BLL.StateQuery)
            Return _states
        End Function

    Notice that it returns a datatable, and it stores the table in the _states variable for use in step 2.

     

    Step 2: Setting the index

    In the case of adding a state all we have to do is call GetStates() and we're finished since it is a new address and they have not picked a state yet.  However, in the EditItemTemplate we must set the state dropdown to the index of the state recorded in the database.  We remember stashing the datatable used to bind the dropdown in the _states variable, now we're going to write a method to find the index of the state from the database.  To do this, we'll call the method from our ascx file like such:

    SelectedIndex='<%# GetStateIndex(DataBinder.Eval(Container, "DataItem.State")) %>

    In the code behind we have created a method that takes in the state of the address and passes out the index of the state in the datatable like such:

        Protected Function GetStateIndex(ByVal stateCode As String) As Integer
            For i As Integer = 0 To _states.DefaultView.Count - 1
                If _states.DefaultView(i)("StateCode") = stateCode Then
                    Return i
                End If
            Next

            Return 0
        End Function

    Like magic, the dropdownlist will now be set to the proper state when a user clicks edit.

     

    Step 3: Handling the state postback

    Now let's look at our second requirement, populating the county list from the state dropdown.  For this to work, we must register the SelectedIndexChanged event for dropdown in both the edititem and the footer.  We'll do this in the ItemCreated() event of the datagrid which is fired every time an item is added to the grid.

        Private Sub dgrAddresses_ItemCreated(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.DataGridItemEventArgs) Handles dgrAddresses.ItemCreated
            If e.Item.ItemType = ListItemType.EditItem Then
                AddHandler CType(e.Item.FindControl("ddlState"), DropDownList).SelectedIndexChanged, AddressOf state_selectedIndexChanged
            End If

            If e.Item.ItemType = ListItemType.Footer Then
                AddHandler CType(e.Item.FindControl("ddlAddState"), DropDownList).SelectedIndexChanged, AddressOf addState_selectedIndexChanged
            End If
        End Sub

    Now when the postback is called from our dropdowns, it knows what method to call.

     

    Step 4: Populating the county list

    Now we must set up the methods to handle the postback event referenced above (addState_selectedIndexChanged and state_selectedIndexChanged).  Each of these methods grabs the sender (state dropdown) to find out which state they picked then queries the database to populate the county list for that state like such:

        Private Sub state_selectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs)
            Dim query As New BLL.CountyQuery("CountyName")
            query.County = New BLL.County
            query.County.StateCode = CType(sender, DropDownList).SelectedItem.Text

            Dim ddlCountyList As DropDownList = CType(dgrAddresses.Items(dgrAddresses.EditItemIndex).FindControl("ddlCounty"), DropDownList)
            ddlCountyList.DataSource = Me.GetDomainManager.ListSummary(query)
            ddlCountyList.DataBind()
        End Sub

        Private Sub addState_selectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs)
            Dim query As New BLL.CountyQuery("CountyName")
            query.County = New BLL.County
            query.County.StateCode = CType(sender, DropDownList).SelectedItem.Text

            Dim FooterIndex As Integer = dgrAddresses.Controls(0).Controls.Count - 1
            Dim ddlCountyList As DropDownList = CType(dgrAddresses.Controls(0).Controls(FooterIndex).FindControl("ddlAddCounty"), DropDownList)
            ddlCountyList.DataSource = Me.GetDomainManager.ListSummary(query)
            ddlCountyList.DataBind()
        End Sub

    Note in the addState_selectedIndexChanged how the FooterIndex is found.  It's something to remember if you ever need to access the footer row of a datagrid.

     

    Step 5: Don't forget about editing the county!

    A small gotcha you run into when editing an existing record is that we've loaded and set the state index and now we have to handle the county dropdown!  The proper place to do this is in the datagrid's ItemDataBound event since at this point the state dropdown has already been filled and set.  (For more on the order of events see MSDN)

    So in our grid itemdatabound we want to see if any of the rows is currently in edit mode, and if so grab the value of the state to load the county list like such:

        Private Sub dgrAddresses_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.DataGridItemEventArgs) Handles dgrAddresses.ItemDataBound
            If dgrAddresses.EditItemIndex >= 0 Then
                If e.Item.ItemIndex = dgrAddresses.EditItemIndex Then
                    'load and set county
                    Dim drv As DataRowView = CType(e.Item.DataItem, DataRowView)

                    Dim query As New BLL.CountyQuery("CountyName")
                    query.County = New BLL.County
                    query.County.StateCode = drv("state")

                    Dim ddlCountyList As DropDownList = CType(e.Item.FindControl("ddlCounty"), DropDownList)
                    ddlCountyList.DataSource = Me.GetDomainManager.ListSummary(query)
                    ddlCountyList.DataBind()

                    Dim li As ListItem = ddlCountyList.Items.FindByText(drv("county"))
                    If Not IsNothing(li) Then li.Selected = True
                End If
            End If

        End Sub

    Note the use of the DataRowView object.  This is a good way to grab the data from the datasource while the grid is being bound.

     

    Conclusion

    Datagrids in ASP .NET are very powerful and flexible.  I hope that the techniques I've shown you today can help you to provide a better user experience!

  • Talk about RAD

    Yeah, I've been scarce lately.  However my custom built domain pattern has saved my butt.

    Project came down to build the administrative and customer portal for a new division www.iambrilliant.com

    Very little in the way of specs, no database, no layout.

    Project deadline: 3 weeks.

    Myself and my two teammates were able to design the database (~35 tables) build the business/data layer, and ~30 pages successfully in this time.  Of course we cheated by putting in about 30 hours of overtime in over July 4th.

    That being said, I'm hella tired.  I have some actual code posts planned, I'll get to them once I recover from the push.

More Posts

Our Sponsors

Proudly Partnered With