Silverlight: Animated "Turbo Tax" style number display

Download Animated Number Project

If you’ve used Turbo Tax, you may have noticed the prominent “Federal Refund” box that’s ever-present at the top of the page while you’re figuring out your taxes. I like this UI concept because when most people are filing their taxes, there’s only one number they actually care about and they care about it every step of the way.

One nice little touch about the display is that whenever you make changes to your return that affect the federal refund, instead of the field just changing immediately, it has a nice incrementing (or decrementing if you’re like me) animation. It is a subtle effect that draws your attention to the field whenever it changes. Try the working example below.


Get Microsoft Silverlight

Recently I worked on a line of business application that would benefit from a similar UI. The application is for pricing out sales proposals and takes into account cost of goods, retail price, agent commission, etc. At every step of the way, slight changes to the various inputs affect the bottom line which is the profitability of the deal. So the profitability is always displayed on the screen. When the value changes, I wanted to have this smooth animation between numbers just like Turbo Tax. Turns out it isn’t that hard.

Before we begin

I just want to note that if I just wanted to create a one-off solution, it could probably be done in about 10 lines of code with event handlers. The purpose of this article is to create a control that is effortless to use and re-use. If you want, you can just skip to the sample project and look at the code. It’s really not that complex.

Creating the Control

The idea is very simple. A control that lets you bind a numeric value to it and when that value changes, the displayed number should quickly increment or decrement to the new value instead of changing immediately. The example above shows the finished control in action.

At first I didn’t want to do this as a control. I thought maybe there was some way I could do it at the binding level or with an attached property but that didn’t seem to be possible via any of the extensibility points offered by Silverlight. So I decided to make it a control.

What kind of control should it be? Should it derive from ContentControl? TextBlock? Neither of those seemed appropriate because in order to make it work, I would need a strongly typed Value property. Having a simple Content property based on System.Object would imply that it could accept any type. I didn’t want to go crazy supporting different types. For example, there’s no point in making it able to animate between two DateTime values or TimeSpan. I decided to stick with System.Double as the type of the Value property. Any numeric type would be convertible to/from Double and there’s a built in DoubleAnimation that I could take advantage of.

I settled on creating a new class called AnimatedNumber that derives from Control (not ContentControl.) I added two dependency properties:

public class AnimatedNumber : Control {
    // the actual code defines theese as dependency properties
    public double Value { get; set; }
    private double AnimatedValue { get; set; }
}

The idea here is that the Value property is the bindable public property that would be set to a discrete value such as 0, 100, 200, etc. When this happens we will animate the private AnimatedValue property so that over a short period of time, the AnimatedValue property will quickly change from 0, 1, 2, … 100, … 198, 199, 200.

To do this, I included a PropertyChangedCallback with the ValueProperty registration. This callback is invoked whenever the Value property is changed (either via x.Value = 100 or as a result of a binding expression.) In the callback, we’ll run a Storyboard against the AnimatedValue property that uses a DoubleAnimation to interpolate between the old and new values.

private static void OnValueChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
    var senderControl = (AnimatedNumber)sender;
    senderControl.AnimateValue((double)e.NewValue);
}

private void AnimateValue(double newValue)
{
    var animation = new DoubleAnimation();
    animation.Duration = TimeSpan.FromSeconds(1);
    animation.To = newValue;

    var storyboard = new Storyboard();
    storyboard.Duration = TimeSpan.FromSeconds(1);
    storyboard.Children.Add(animation);

    Storyboard.SetTarget(animation, this);
    Storyboard.SetTargetProperty(animation, new PropertyPath("AnimatedValue"));

    storyboard.Begin();
}

So now we have a control that exposes a Value that when changed, triggers an incremental change to the new value in a corresponding AnimatedValue property. But so far, the control has absolutely no visual representation! We’ve only defined the behavior of the control.

Creating a Default Control Template

To add a default control template, add a folder named “Themes” to the root of the project and create a resource dictionary named Generic.xaml. Add a style with no key and a setter that defines a very basic control template. In fact, the only thing this control has is a ContentPresenter that will present the AnimatedValue property. The entire Generic.xaml is only a few lines long. The control doesn’t need anything more than that because we eventually want to use it wherever we’d place “content” such as in a button or label. Let some other control provide the eye candy.



    

The important thing is that we have a ContentPresenter named (exactly) PART_Content. You’ll see why in a second.

To make Silverlight associate the above template with our control, we need to add a line to the constructor, and while we’re at it, override OnApplyTemplate. This is the best place to grab the template part we expect to find (PART_Content) and bind it to the AnimatedValue property.

// Template part
private ContentPresenter PART_Content;

// Default public constructor
public AnimatedNumber() {
    DefaultStyleKey = typeof(AnimatedNumber);
}

protected override void OnApplyTemplate() {

    base.OnApplyTemplate();

    PART_Content = GetTemplateChild("PART_Content") as ContentPresenter;
    if (PART_Content != null) {
        var binding = new Binding("AnimatedValue");
        binding.Source = this;
        PART_Content.SetBinding(ContentPresenter.ContentProperty, binding);
    }

}

Okay, now in theory it should work but I would advise reading the next section first and looking at the *actual* code I attached as opposed to the select snippets I put inline.

Okay, now it should work…

Really this is all that is needed to make the control functional. But it’s a little crude. The attached sample project is a bit more cleaned up than the inline code so far. There’s also additional functionality.

For one, the code above would use the default Double.ToString() conversion which means as the animation was in progress, you’d probably see a huge ugly number with lots of decimal places, no separators, and no currency symbols. The attached control adds a Format property and uses an included FormattingValueConverter. This way you can specify a format string as an attribute in the XAML to get the nice formatting as seen in the demo at the beginning of the article.

Also, the attached control does not create a new Storyboard everytime the value is animated. A single Storyboard is created in the constructor and is reused for the life of the control. The nice thing about this is that multiple changes to the value will “interrupt” the previous animation. So for example if it’s halfway through animation from 0 to 100 and you change it back to 0, it won’t continue to climb to 100 then drop to 0. It will stop climbing at 50 or whatever, and start dropping.

Finally, the attached control provides a TransitionDuration property that lets you control how long the control will spend transitioning. Right now the time is constant which is a little weird.

Using the code is pretty straightforward. The following is an example of a simple button that is bound to a TotalProfit value of the ViewModel and animates the value when it changes.

Ideas for Additional Improvements

Some things that I didn’t have time to get to but would be nice:

  • Using an easing function to make the animation more fluid
  • Varying the duration of the animation based on how large or small the change is. For example if you changed 1000 to 1009, it’s kind of silly that the control spends 2 seconds making that transition.
  • Adding support for the Visual State Manager. In particular, it would be nice to have 3 states – Positive, Zero, Negative. This way you could color the value red when negative and green when positive without putting too much burden on the consumer of the control.

Please let me know what you think of this example. It’s my first time posting a lenthy example of a Silverlight control but as time permits I’d like to share more of my recent experiences.

Download Animated Number Project

  • Share/Bookmark

Google begins phasing out support for legacy versions of Internet Explorer

And hopefully many more will follow suit. SharePoint 2010 also does not support IE6. Hopefully this will hasten it’s demise.

Dear Google Apps admin,​

In order to continue to improve our products and deliver more sophisticated features and performance, we are harnessing some of the latest improvements in web browser technology.  This includes faster JavaScript processing and new standards like HTML5.  As a result, over the course of 2010, we will be phasing out support for Microsoft Internet Explorer 6.0 as well as other older browsers that are not supported by their own manufacturers.

We plan to begin phasing out support of these older browsers on the Google Docs suite and the Google Sites editor on March 1, 2010.  After that point, certain functionality within these applications may have higher latency and may not work correctly in these older browsers. Later in 2010, we will start to phase out support for these browsers for Google Mail and Google Calendar.

Google Apps will continue to support Internet Explorer 7.0 and above, Firefox 3.0 and above, Google Chrome 4.0 and above, and Safari 3.0 and above.

Starting this week, users on these older browsers will see a message in Google Docs and the Google Sites editor explaining this change and asking them to upgrade their browser.  We will also alert you again closer to March 1 to remind you of this change.

In 2009, the Google Apps team delivered more than 100 improvements to enhance your product experience. We are aiming to beat that in 2010 and continue to deliver the best and most innovative collaboration products for businesses.

Thank you for your continued support!

Sincerely,

The Google Apps team

Email preferences: You have received this mandatory email service announcement to update you about important changes to your Google Apps product or account.

Google Inc.
1600 Amphitheatre Parkway
Mountain View, CA 94043

  • Share/Bookmark

Awesome Extension Methods: In and Between

These ones are pretty simple in implementation but go a long way to cleaning up your code. In some cases, the slight performance overhead may not be acceptable but I haven’t run into any real-world problems with them. Check out the usage below.

int x = 3;

// is x either 1, 3, or 5?
if (x.In(1, 3, 5)) {
    // yes!
}

// is x between 1 and 5?
if (x.Between(1, 5)) {
    // yes!
}

The In method works with any kind of object and uses the default EqualityComparer<T> implementation for the type. But there are overloads that specify common types such as int, byte, long, etc. These overloads will perform much better than the generic overload. There is also an overload for String that takes a comparer so that you can specify case-insensitive matching as needed.

The Between method works on any type implementing IComparable. It also has overloads for commonly used types to get better performance than using the default IComparable implementation.

The code for both extension methods is shown below.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Einstein
{

    /// <summary>
    /// Extension methods for <see cref="T:IComparable"/> types.
    /// </summary>
    public static class ComparableExtensions
    {

        #region Methods

        #region In

        /// <summary>
        /// Determines whether this value exists in the <paramref name="set"/> passed.
        /// </summary>
        /// <typeparam name="T">The type of the value to compare and the values in the set.</typeparam>
        /// <param name="value">The value.</param>
        /// <param name="comparer">The comparer to use.</param>
        /// <param name="set">The set of values to determine if <paramref name="value"/> is in.</param>
        /// <returns>True if <paramref name="value"/> exists in the <paramref name="set"/> otherwise, false.</returns>
        public static bool In<T>( this T value, IEqualityComparer<T> comparer, params T[] set )
        {

            // Use default comparer
            if ( comparer == null ) {
                comparer = EqualityComparer<T>.Default;
            }   // if

            // Constant false
            if ( set.Length == 0 ) {
                return false;
            }   // if

            for ( int i = 0; i < set.Length; i++ ) {
                if ( comparer.Equals( value, set[i] ) ) {
                    return true;
                }   // if
            }   // for

            return false;

        }

        /// <summary>
        /// Determines whether this value exists in the <paramref name="set"/> passed.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <param name="set">The set of values to determine if <paramref name="value"/> is in.</param>
        /// <returns>True if <paramref name="value"/> exists in the <paramref name="set"/> otherwise, false.</returns>
        public static bool In( this byte value, params byte[] set )
        {
            for ( int i = 0; i < set.Length; i++ ) {
                if ( value == set[i] ) {
                    return true;
                }   // if
            }   // for
            return false;
        }

        /// <summary>
        /// Determines whether this value exists in the <paramref name="set"/> passed.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <param name="set">The set of values to determine if <paramref name="value"/> is in.</param>
        /// <returns>True if <paramref name="value"/> exists in the <paramref name="set"/> otherwise, false.</returns>
        public static bool In( this short value, params short[] set )
        {
            for ( int i = 0; i < set.Length; i++ ) {
                if ( value == set[i] ) {
                    return true;
                }   // if
            }   // for
            return false;
        }

        /// <summary>
        /// Determines whether this value exists in the <paramref name="set"/> passed.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <param name="set">The set of values to determine if <paramref name="value"/> is in.</param>
        /// <returns>True if <paramref name="value"/> exists in the <paramref name="set"/> otherwise, false.</returns>
        public static bool In( this int value, params int[] set )
        {
            for ( int i = 0; i < set.Length; i++ ) {
                if ( value == set[i] ) {
                    return true;
                }   // if
            }   // for
            return false;
        }

        /// <summary>
        /// Determines whether this value exists in the <paramref name="set"/> passed.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <param name="set">The set of values to determine if <paramref name="value"/> is in.</param>
        /// <returns>True if <paramref name="value"/> exists in the <paramref name="set"/> otherwise, false.</returns>
        public static bool In( this long value, params long[] set )
        {
            for ( int i = 0; i < set.Length; i++ ) {
                if ( value == set[i] ) {
                    return true;
                }   // if
            }   // for
            return false;
        }

        /// <summary>
        /// Determines whether this value exists in the <paramref name="set"/> passed.
        /// </summary>
        /// <param name="value">The value.</param>
        /// <param name="set">The set of values to determine if <paramref name="value"/> is in.</param>
        /// <returns>True if <paramref name="value"/> exists in the <paramref name="set"/> otherwise, false.</returns>
        public static bool In( this string value, params string[] set )
        {
            return In<string>( value, StringComparer.OrdinalIgnoreCase, set );
        }

        /// <summary>
        /// Determines whether this value exists in the <paramref name="set"/> passed.
        /// </summary>
        /// <typeparam name="T">The type of the value to compare and the values in the set.</typeparam>
        /// <param name="value">The value.</param>
        /// <param name="set">The set of values to determine if <paramref name="value"/> is in.</param>
        /// <returns>True if <paramref name="value"/> exists in the <paramref name="set"/> otherwise, false.</returns>
        public static bool In<T>( this T value, params T[] set )
        {
            return In<T>( value, EqualityComparer<T>.Default, set );
        }

        #endregion

        #region Between

        /// <summary>
        /// Determines if the <paramref name="value"/> is between <paramref name="minValueInclusive"/> and
        /// <paramref name="maxValueInclusive"/>.
        /// </summary>
        /// <typeparam name="T">The type of values to compare.</typeparam>
        /// <param name="value">The value to check.</param>
        /// <param name="minValueInclusive">The min value inclusive.</param>
        /// <param name="maxValueInclusive">The max value inclusive.</param>
        /// <returns>True if <paramref name="value"/> is between <paramref name="minValueInclusive"/> and
        /// <paramref name="maxValueInclusive"/>, otherwise false.</returns>
        public static bool Between<T>( this T value, T minValueInclusive, T maxValueInclusive ) where T : IComparable
        {

            ParameterValidation.ThrowIfNull( value, "value" );

            int o1 = value.CompareTo( minValueInclusive );
            int o2 = value.CompareTo( maxValueInclusive );

            return ( o1 >= 0 && o2 <= 0 ) || ( o1 <= 0 && o2 >= 0 );

        }

        /// <summary>
        /// Determines if the <paramref name="value"/> is between <paramref name="minValueInclusive"/> and
        /// <paramref name="maxValueInclusive"/>.
        /// </summary>
        /// <param name="value">The value to check.</param>
        /// <param name="minValueInclusive">The min value inclusive.</param>
        /// <param name="maxValueInclusive">The max value inclusive.</param>
        /// <returns>True if <paramref name="value"/> is between <paramref name="minValueInclusive"/> and
        /// <paramref name="maxValueInclusive"/>, otherwise false.</returns>
        public static bool Between( this byte value, byte minValueInclusive, byte maxValueInclusive )
        {
            if ( minValueInclusive <= maxValueInclusive ) {
                return ( value >= minValueInclusive ) && ( value <= maxValueInclusive );
            }   // if
            else {
                return ( value >= maxValueInclusive ) && ( value <= minValueInclusive );
            }   // else
        }

        /// <summary>
        /// Determines if the <paramref name="value"/> is between <paramref name="minValueInclusive"/> and
        /// <paramref name="maxValueInclusive"/>.
        /// </summary>
        /// <param name="value">The value to check.</param>
        /// <param name="minValueInclusive">The min value inclusive.</param>
        /// <param name="maxValueInclusive">The max value inclusive.</param>
        /// <returns>True if <paramref name="value"/> is between <paramref name="minValueInclusive"/> and
        /// <paramref name="maxValueInclusive"/>, otherwise false.</returns>
        public static bool Between( this short value, short minValueInclusive, short maxValueInclusive )
        {
            if ( minValueInclusive <= maxValueInclusive ) {
                return ( value >= minValueInclusive ) && ( value <= maxValueInclusive );
            }   // if
            else {
                return ( value >= maxValueInclusive ) && ( value <= minValueInclusive );
            }   // else
        }

        /// <summary>
        /// Determines if the <paramref name="value"/> is between <paramref name="minValueInclusive"/> and
        /// <paramref name="maxValueInclusive"/>.
        /// </summary>
        /// <param name="value">The value to check.</param>
        /// <param name="minValueInclusive">The min value inclusive.</param>
        /// <param name="maxValueInclusive">The max value inclusive.</param>
        /// <returns>True if <paramref name="value"/> is between <paramref name="minValueInclusive"/> and
        /// <paramref name="maxValueInclusive"/>, otherwise false.</returns>
        public static bool Between( this int value, int minValueInclusive, int maxValueInclusive )
        {
            if ( minValueInclusive <= maxValueInclusive ) {
                return ( value >= minValueInclusive ) && ( value <= maxValueInclusive );
            }   // if
            else {
                return ( value >= maxValueInclusive ) && ( value <= minValueInclusive );
            }   // else
        }

        /// <summary>
        /// Determines if the <paramref name="value"/> is between <paramref name="minValueInclusive"/> and
        /// <paramref name="maxValueInclusive"/>.
        /// </summary>
        /// <param name="value">The value to check.</param>
        /// <param name="minValueInclusive">The min value inclusive.</param>
        /// <param name="maxValueInclusive">The max value inclusive.</param>
        /// <returns>True if <paramref name="value"/> is between <paramref name="minValueInclusive"/> and
        /// <paramref name="maxValueInclusive"/>, otherwise false.</returns>
        public static bool Between( this long value, long minValueInclusive, long maxValueInclusive )
        {
            if ( minValueInclusive <= maxValueInclusive ) {
                return ( value >= minValueInclusive ) && ( value <= maxValueInclusive );
            }   // if
            else {
                return ( value >= maxValueInclusive ) && ( value <= minValueInclusive );
            }   // else
        }

        /// <summary>
        /// Determines if the <paramref name="value"/> is between <paramref name="minValueInclusive"/> and
        /// <paramref name="maxValueInclusive"/>.
        /// </summary>
        /// <param name="value">The value to check.</param>
        /// <param name="minValueInclusive">The min value inclusive.</param>
        /// <param name="maxValueInclusive">The max value inclusive.</param>
        /// <returns>True if <paramref name="value"/> is between <paramref name="minValueInclusive"/> and
        /// <paramref name="maxValueInclusive"/>, otherwise false.</returns>
        public static bool Between( this decimal value, decimal minValueInclusive, decimal maxValueInclusive )
        {
            if ( minValueInclusive <= maxValueInclusive ) {
                return ( value >= minValueInclusive ) && ( value <= maxValueInclusive );
            }   // if
            else {
                return ( value >= maxValueInclusive ) && ( value <= minValueInclusive );
            }   // else
        }

        /// <summary>
        /// Determines if the <paramref name="value"/> is between <paramref name="minValueInclusive"/> and
        /// <paramref name="maxValueInclusive"/>.
        /// </summary>
        /// <param name="value">The value to check.</param>
        /// <param name="minValueInclusive">The min value inclusive.</param>
        /// <param name="maxValueInclusive">The max value inclusive.</param>
        /// <returns>True if <paramref name="value"/> is between <paramref name="minValueInclusive"/> and
        /// <paramref name="maxValueInclusive"/>, otherwise false.</returns>
        public static bool Between( this float value, float minValueInclusive, float maxValueInclusive )
        {
            if ( minValueInclusive <= maxValueInclusive ) {
                return ( value >= minValueInclusive ) && ( value <= maxValueInclusive );
            }   // if
            else {
                return ( value >= maxValueInclusive ) && ( value <= minValueInclusive );
            }   // else
        }

        /// <summary>
        /// Determines if the <paramref name="value"/> is between <paramref name="minValueInclusive"/> and
        /// <paramref name="maxValueInclusive"/>.
        /// </summary>
        /// <param name="value">The value to check.</param>
        /// <param name="minValueInclusive">The min value inclusive.</param>
        /// <param name="maxValueInclusive">The max value inclusive.</param>
        /// <returns>True if <paramref name="value"/> is between <paramref name="minValueInclusive"/> and
        /// <paramref name="maxValueInclusive"/>, otherwise false.</returns>
        public static bool Between( this double value, double minValueInclusive, double maxValueInclusive )
        {
            if ( minValueInclusive <= maxValueInclusive ) {
                return ( value >= minValueInclusive ) && ( value <= maxValueInclusive );
            }   // if
            else {
                return ( value >= maxValueInclusive ) && ( value <= minValueInclusive );
            }   // else
        }

        /// <summary>
        /// Determines if the <paramref name="value"/> is between <paramref name="minValueInclusive"/> and
        /// <paramref name="maxValueInclusive"/>.
        /// </summary>
        /// <param name="value">The value to check.</param>
        /// <param name="minValueInclusive">The min value inclusive.</param>
        /// <param name="maxValueInclusive">The max value inclusive.</param>
        /// <returns>True if <paramref name="value"/> is between <paramref name="minValueInclusive"/> and
        /// <paramref name="maxValueInclusive"/>, otherwise false.</returns>
        public static bool Between( this DateTime value, DateTime minValueInclusive, DateTime maxValueInclusive )
        {
            if ( minValueInclusive <= maxValueInclusive ) {
                return ( value >= minValueInclusive ) && ( value <= maxValueInclusive );
            }   // if
            else {
                return ( value >= maxValueInclusive ) && ( value <= minValueInclusive );
            }   // else
        }

        /// <summary>
        /// Determines if the <paramref name="value"/> is between <paramref name="minValueInclusive"/> and
        /// <paramref name="maxValueInclusive"/>.
        /// </summary>
        /// <param name="value">The value to check.</param>
        /// <param name="minValueInclusive">The min value inclusive.</param>
        /// <param name="maxValueInclusive">The max value inclusive.</param>
        /// <returns>True if <paramref name="value"/> is between <paramref name="minValueInclusive"/> and
        /// <paramref name="maxValueInclusive"/>, otherwise false.</returns>
        public static bool Between( this TimeSpan value, TimeSpan minValueInclusive, TimeSpan maxValueInclusive )
        {
            if ( minValueInclusive <= maxValueInclusive ) {
                return ( value >= minValueInclusive ) && ( value <= maxValueInclusive );
            }   // if
            else {
                return ( value >= maxValueInclusive ) && ( value <= minValueInclusive );
            }   // else
        }

        #endregion

        #endregion

    }   // class

}   // namespace
  • Share/Bookmark

How would you like to lose your job to a 9 year old?

9-Year-Old is World's Youngest Microsoft Certified Systems Engineer This is pretty impressive. When I was 9 I was still trying to figure out how I could get Guns N’ Roses to come to my birthday party. Of course the cynics will probably claim it is a reflection of the MCSE certification, but how can you not be impressed?

9-Year-Old is World’s Youngest Microsoft Certified Systems Engineer

via Doug Finke

  • Share/Bookmark

Yes we can! Scott Brown wins MA special election!

Epic Upset

Sure, it’s a victory for the GOP. But more importantly, it’s a victory for “just right of center” moderates and independents like me. Scott Brown’s astonishing defeat of Martha Coakley, the one “chosen” to replace the late Ted Kennedy, sends a dual message to both the right and left – don’t f*ck with the independents!

While it’s partly true that Democrats left the plane on autopilot, assuming a liberal state like Massachusetts was in the bag, Scott Brown also is a very effective campaigner. On the national stage, he found the right message to attract the right donors and supporters. But at the local level, he struck the right balance between “change” and “mutiny.” Then there’s that little issue of our fearless leader marching in to save the day with his elitist jabs at average everyday people who drive trucks.

But conservatives from outside the state could have just as easily screwed the whole thing up. After the way the tea party purists botched the NY-23 election in November, I was quite worried that the GOP would fracture and turn to cannibalism in an effort to weed out those they deemed were not falling in line. It doesn’t take a genius to realize that you can’t win elections by purging voters. But in November, it seemed as though logic was out the window when they literally handed a seat to the Democrats because a bunch of outsiders didn’t like the nominee.

Glenn Beck and Rush Limbaugh would never get behind a candidate like Chris Christie if given the choice between him and a much more conservative candidate. But had Steve Lonegan (the “conservative” choice) won the NJ primary, MSNBC would be talking to Gov. Jon Corzine tonight. Instead, Gov. Chris Christie was elected and today he was inaugurated.

When your car is out of control and veering to the left, your natural instinct is to jerk the wheel to the right. But in doing so, you make the problem worse and you may never regain control. So while there’s still a lot of work to do to restore balance to our government, today is a good day and 2010 is off to a great start.

  • Share/Bookmark

AT&T fixes bug that logged users into random Facebook accounts

Note sure how Facebook gets off the hook on this one. This is entirely a *Facebook* problem, not AT&T. If Facebook wasn’t developed by morons with no regard for privacy and security, this bug wouldn’t be possible.

AT&T fixes bug that logged users into random Facebook accounts

Okay, so we were under the impression that Facebook login credentials were a locally-managed affair, but it looks like almost anything can break when AT&T’s involved — according to CNET, the carrier just fixed "several problems" that had users logging into the wrong Facebook account from their phones.
  • Share/Bookmark

Ed Bott: It’s time to stop using IE6

Ed Bott has thrown down the gauntlet when it comes to companies that still use Internet Explorer 6. Users stuck on IE6 are one of the main reasons IE still has such a bad reputation when it comes to security even though Firefox and Safari were found to be far more vulnerable than Internet Explorer in 2009. And according to Ed, allowing people to use IE6 is akin to IT-malpractice.

Any IT professional who is still allowing IE6 to be used in a corporate setting is guilty of malpractice. Think that judgment is too harsh? Ask the security experts at Google, Adobe, and dozens of other large corporations that are cleaning up the mess from a wave of targeted attacks that allowed source code and confidential data to fall into the hands of well-organized intruders. The entry point? According to Microsoft, it’s IE6.

First, upgrade to Internet Explorer 8 if you haven’t already.

Then, read more: It’s time to stop using IE6

  • Share/Bookmark

Easy way to prevent WebBrowser control from using window.alert

There are all sorts of official ways of doing this implementing various IE hosting interfaces in order to handle the presentation of the UI. But if you’re trying to automate a web page and a pesky window.alert is blocking your progress, the following code will supress it for the current page.

/// <summary>
/// Handles the Navigated event of the browser control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="T:WebBrowserNavigatedEventArgs"/> instance containing the
/// event data.</param>
private void browser_Navigated( object sender, WebBrowserNavigatedEventArgs e )
{

    if ( browser.Document != null ) {

        // kills messagebox functionality by disabling the "window.alert()" function
        object window = browser.Document.Window.DomWindow;
        if ( window != null ) {
            Type windowType = window.GetType();
            BindingFlags flags = BindingFlags.InvokeMethod | BindingFlags.Instance;
            string[] args = { "window.alert=function() {};", "JScript" };
            windowType.InvokeMember( "[DispID=1165]", flags, null, window, args );
        }   // if

    }   // if

}
  • Share/Bookmark

Awesome Extension Methods: IEnumerable.Batch

.NET 3.5 brought a bunch of great extension methods to the framework, most of which extended the IEnumerable<T> (or IQueryable<T>) interfaces implemented by just about every collection type. These include simple ones such as Where, OrderBy, FirstOrDefault, etc as well as more complex ones like Aggregate, GroupBy, etc. The Enumerable class really covers a lot of ground, but I’ve created a couple more that I use from time to time in my “Common” assembly.

The extension method I’m writing about today is called Batch. It allows you to take any input sequence (array, collection, iterator, etc.) and process it in batches of a specified size.

Many times you will have an input sequence that contains a lot of items but for various reasons, you can’t process the entire sequence at once (memory constraints, you want to update a console with progress, etc.) and processing one at a time is too slow.

Before, I used to write code that would look like this.

var batch = new List();

foreach (var item in sequence) {

    batch.Add(item);

    if (batch.Count == 100) {
        BulkInsert(batch);
        batch.Clear();
    }

}

This isn’t too bad but it’s a lot of ceremony and extension methods are all about turning globs like that into more readable, concise code. The method signature for the Batch method looks like the following.

/// <summary>
/// Enumerates a sequence in chunks, yielding batches of a certain size to the enumerator.
/// </summary>
/// <typeparam name="T">The type of item in the batch.</typeparam>
/// <param name="sequence">The sequence of items to be enumerated.</param>
/// <param name="batchSize">The maximum number of items to include in a batch.</param>
/// <returns>A sequence of arrays, with each array containing at most
/// <paramref name="batchSize"/> elements.</returns>
public static IEnumerable<T[]> Batch<T>( this IEnumerable<T> sequence, int batchSize )

As the summary suggests, it converts an input sequence into a sequence of arrays of a specified size. The last array in the sequence will have fewer items than the batch size if the input count is not evenly divisible by batchSize. Calling it is very simple. The first example can be rewritten as the following.

foreach (Record[] batch in sequence.Batch(100)) {
    BulkInsert(batch);
}

The complete code example is shown below.

/// <summary>
/// Enumerates a sequence in chunks, yielding batches of a certain size to the enumerator.
/// </summary>
/// <typeparam name="T">The type of item in the batch.</typeparam>
/// <param name="sequence">The sequence of items to be enumerated.</param>
/// <param name="batchSize">The maximum number of items to include in a batch.</param>
/// <returns>A sequence of arrays, with each array containing at most
/// <paramref name="batchSize"/> elements.</returns>
public static IEnumerable<T[]> Batch<T>( this IEnumerable<T> sequence, int batchSize )
{

    var batch = new List<T>( batchSize );

    foreach ( var item in sequence ) {

        batch.Add( item );

        // when we've accumulated enough in the
        // batch, send it out
        if ( batch.Count >= batchSize ) {
            yield return batch.ToArray( );
            batch.Clear( );
        }   // if

    }   // foreach

    // send out any leftovers
    if ( batch.Count > 0 ) {
        yield return batch.ToArray( );
        batch.Clear( );
    }   // if

}
  • Share/Bookmark

Awesome Extension Methods: String.MatchInto

Regular Expressions in .NET are pretty easy to use (assuming you understand the Regex syntax which is beside the case) and certainly you can think of some useful extension methods for System.String that would allow you to quickly validate against a particular regular expression pattern. But regular expressions have another great feature that you maybe don’t use as much – that is the ability to capture subexpressions into groups so that you can pull out a piece of the match.

The way this is done using the Regex class is pretty straightforward.

// Find a word that starts with H and W
string input = "Hello World";
string pattern = @"(H\w+) (W\w+)";

Match m = Regex.Match(input, pattern);
if (m.Success) {
    string hWord = m.Groups[1].Value;
    string wWord = m.Groups[2].Value;
}

This is easy enough, but I am annnoyed by the code that accesses the groups. It seems like such a mundane detail to worry about Group and Match objects. What if the code could be simplified like the following:

string input = "Hello World";
string pattern = @"(H\w+) (W\w+)";

string hWord, wWord;
if (input.MatchInto(pattern, out hWord, out wWord)) ...

It may not look like much of a savings in terms of lines of code, but I find that it looks much cleaner and is a lot less explicit. The full code is below.

/// <summary>
/// Performs a regular expression match against the specified string, and places the captured groups into the output parameters.
/// </summary>
/// <param name="input">The input string to match against.</param>
/// <param name="pattern">The regular expression pattern which should contain grouping expressions.</param>
/// <param name="value1">Receives the value of the 1st capture group (Groups[1]) or null if no match was made.</param>
/// <param name="value2">Receives the value of the 2nd capture group (Groups[2]) or null if no match was made.</param>
/// <param name="value3">Receives the value of the 3rd capture group (Groups[3]) or null if no match was made.</param>
/// <param name="value4">Receives the value of the 4th capture group (Groups[4]) or null if no match was made.</param>
/// <param name="value5">Receives the value of the 5th capture group (Groups[5]) or null if no match was made.</param>
/// <returns>True if the pattern matched (not necessarily all groups) otherwise false.</returns>
public static bool MatchInto( this string input, string pattern, out string value1, out string value2, out string value3, out string value4, out string value5 )
{

    value1 = value2 = value3 = value4 = value5 = null;

    var match = Match( input, pattern );
    if ( match.Success ) {

        // Value1
        if ( match.Groups.Count > 1 && match.Groups[1].Success ) {
            value1 = match.Groups[1].Value;
        }   // if

        // Value2
        if ( match.Groups.Count > 2 && match.Groups[2].Success ) {
            value2 = match.Groups[2].Value;
        }   // if

        // Value3
        if ( match.Groups.Count > 3 && match.Groups[3].Success ) {
            value3 = match.Groups[3].Value;
        }   // if

        // Value4
        if ( match.Groups.Count > 4 && match.Groups[4].Success ) {
            value4 = match.Groups[4].Value;
        }   // if

        // Value5
        if ( match.Groups.Count > 5 && match.Groups[5].Success ) {
            value5 = match.Groups[5].Value;
        }   // if

        return true;

    }   // if

    return false;

}

/// <summary>
/// Performs a regular expression match against the specified string, and places the captured groups into the output parameters.
/// </summary>
/// <param name="input">The input string to match against.</param>
/// <param name="pattern">The regular expression pattern which should contain grouping expressions.</param>
/// <param name="value1">Receives the value of the 1st capture group (Groups[1]) or null if no match was made.</param>
/// <param name="value2">Receives the value of the 2nd capture group (Groups[2]) or null if no match was made.</param>
/// <param name="value3">Receives the value of the 3rd capture group (Groups[3]) or null if no match was made.</param>
/// <param name="value4">Receives the value of the 4th capture group (Groups[4]) or null if no match was made.</param>
/// <returns>True if the pattern matched (not necessarily all groups) otherwise false.</returns>
public static bool MatchInto( this string input, string pattern, out string value1, out string value2, out string value3, out string value4 )
{
    string value5;
    return MatchInto( input, pattern, out value1, out value2, out value3, out value4, out value5 );
}

/// <summary>
/// Performs a regular expression match against the specified string, and places the captured groups into the output parameters.
/// </summary>
/// <param name="input">The input string to match against.</param>
/// <param name="pattern">The regular expression pattern which should contain grouping expressions.</param>
/// <param name="value1">Receives the value of the 1st capture group (Groups[1]) or null if no match was made.</param>
/// <param name="value2">Receives the value of the 2nd capture group (Groups[2]) or null if no match was made.</param>
/// <param name="value3">Receives the value of the 3rd capture group (Groups[3]) or null if no match was made.</param>
/// <returns>True if the pattern matched (not necessarily all groups) otherwise false.</returns>
public static bool MatchInto( this string input, string pattern, out string value1, out string value2, out string value3 )
{
    string value4;
    string value5;
    return MatchInto( input, pattern, out value1, out value2, out value3, out value4, out value5 );
}

/// <summary>
/// Performs a regular expression match against the specified string, and places the captured groups into the output parameters.
/// </summary>
/// <param name="input">The input string to match against.</param>
/// <param name="pattern">The regular expression pattern which should contain grouping expressions.</param>
/// <param name="value1">Receives the value of the 1st capture group (Groups[1]) or null if no match was made.</param>
/// <param name="value2">Receives the value of the 2nd capture group (Groups[2]) or null if no match was made.</param>
/// <returns>True if the pattern matched (not necessarily all groups) otherwise false.</returns>
public static bool MatchInto( this string input, string pattern, out string value1, out string value2 )
{
    string value3;
    string value4;
    string value5;
    return MatchInto( input, pattern, out value1, out value2, out value3, out value4, out value5 );
}

/// <summary>
/// Performs a regular expression match against the specified string, and places the captured groups into the output parameters.
/// </summary>
/// <param name="input">The input string to match against.</param>
/// <param name="pattern">The regular expression pattern which should contain grouping expressions.</param>
/// <param name="value">Receives the value of the 1st capture group (Groups[1]) or null if no match was made.</param>
/// <returns>True if the pattern matched (not necessarily all groups) otherwise false.</returns>
public static bool MatchInto( this string input, string pattern, out string value )
{
    string value2;
    string value3;
    string value4;
    string value5;
    return MatchInto( input, pattern, out value, out value2, out value3, out value4, out value5 );
}
  • Share/Bookmark