Scott Hanselman

Hanselminutes Podcast 124 - Tim Bray on Microblogging and Widefinder

August 01, 2008 Comment on this post [2] Posted in Podcast
Sponsored By

Tim My one-hundred-and-twenty-fourth podcast is up. This interview was setup on Twitter. Tim Bray is a Distinguished Engineer at Sun. He co-edited the XML and XML namespace specs back in the day as well as working on Atom. He is on Twitter at http://twitter.com/timbray. Tim has been running the Wide Finder 2 Project that you can learn more about at the Wide Finder Project Wiki. It is an attempt to answer this interesting question: "What is a good way to write computer programs to take advantage of modern slow-clock-rate/many-core computers, without imposing excessive complexity on programmers?"

Subscribe: Subscribe to Hanselminutes Subscribe to my Podcast in iTunes

If you have trouble downloading, or your download is slow, do try the torrent with µtorrent or another BitTorrent Downloader.

Do also remember the complete archives are always up and they have PDF Transcripts, a little known feature that show up a few weeks after each show.

Telerik is our sponsor for this show.

Telerik's new stuff is pretty sweet, check out the ONLINE DEMO of their new ASP.NET AJAX suite. RadGrid handles sorting, filtering, and paging of hundreds of thousands of records in milliseconds, and the RadEditor loads up to 4 times faster and the navigation controls now support binding to web services on the client.

As I've said before this show comes to you with the audio expertise and stewardship of Carl Franklin. The name comes from Travis Illig, but the goal of the show is simple. Avoid wasting the listener's time. (and make the commute less boring)

Enjoy. Who knows what'll happen in the next show?

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service

Learning WPF with BabySmash - Manually Managing ClickOnce and some more Designer Goodness

August 01, 2008 Comment on this post [22] Posted in BabySmash | Windows Client | WPF
Sponsored By

NOTE: If you haven't read the first post in this series, I would encourage you do to that first, or check out the BabySmash category. Also check out http://windowsclient.net/ for more developer info on WPF.

BACKGROUND: This is one of a series of posts on learning WPF. I wrote an application for my 2 year old using WPF, but as I'm a Win32-minded programmer, my working app is full of Win32-isms. It's not a good example of a WPF application even though it uses the technology. I'm calling on community (that's you, Dear Reader) to blog about your solutions to different (horrible) selections of my code. You can get the code http://www.codeplex.com/babysmash. Post your solutions on your blog, in the comments, or in the Feedback and we'll all learn WPF together. Pick a single line, a section, or subsystem or the whole app!

One of the pieces of feedback on BabySmash! was that even though people like that the application automatically updates (via ClickOnce) when they sit down to play BabySmash! their babies want to play it NOW. They didn't like that it tries to update itself when you launch it.

When you setup a ClickOnce application, you get a few choices. You can have the application check for updates before it starts and applying updates before it starts, or you can have it check after it starts and install the updates the next time it starts up. Or, you can say Don't Check For Updates.

I personally find this dialog a little confusing. What this really means is "I'll check manually in code."

Application Updates

At this point, I'm still deploying my app as a ClickOnce app, but now the actual updating is up to me. I used to pop up the Options dialog every time the app started, but again, folks complained, so I had to figure out a way to let them know that an update is available without "stopping the action."

When the app starts up now, it fires of a call to CheckForUpdateAsync from inside System.Deployment.Application and listens for a response. This happens in the background (hence "async"):

if (ApplicationDeployment.IsNetworkDeployed)
{
ApplicationDeployment deployment = ApplicationDeployment.CurrentDeployment;
deployment.CheckForUpdateCompleted += deployment_CheckForUpdateCompleted;
try
{
deployment.CheckForUpdateAsync();
}
catch (InvalidOperationException e)
{
Debug.WriteLine(e.ToString());
}
}

If there is an update, I show a label in each MainWindow:

void deployment_CheckForUpdateCompleted(object sender, CheckForUpdateCompletedEventArgs e)
{
ClickOnceUpdateAvailable = e.UpdateAvailable;
if (ClickOnceUpdateAvailable)
{
foreach (MainWindow m in this.windows)
{
m.UpdateAvailableLabel.Visibility = Visibility.Visible;
}
}
}

The label is really simple, just a label with a glow:

<TextBlock x:Name="UpdateAvailableLabel" Visibility="Collapsed" Margin="15,0,0,0" FontSize="12">
<TextBlock.BitmapEffect>
<BitmapEffectGroup>
<OuterGlowBitmapEffect x:Name="UpdateGlow" GlowColor="Red" GlowSize="3"/>
</BitmapEffectGroup>
</TextBlock.BitmapEffect>
<Bold>Update Available - Visit Options to Update BabySmash!</Bold>
</TextBlock>

Except the glow "pulses" between three colors and repeats forever. I set the DesiredFrameRate to a low number like 10 fps rather than what WPF will attempt, which is 60 fps! I'll post later how we can detect how awesome the user's hardware is and scale or turn off animations and effects.

<Window.Resources>
<Storyboard x:Key="Timeline1" Timeline.DesiredFrameRate="10">
<ColorAnimationUsingKeyFrames BeginTime="00:00:00" RepeatBehavior="Forever"
AutoReverse="True" Storyboard.TargetName="UpdateGlow"
Storyboard.TargetProperty="GlowColor" >
<SplineColorKeyFrame Value="#FFCDCDCD" KeyTime="00:00:00"/>
<SplineColorKeyFrame Value="#FFB92121" KeyTime="00:00:01"/>
<SplineColorKeyFrame Value="#FF2921B9" KeyTime="00:00:02"/>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</Window.Resources>

<Window.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard Storyboard="{StaticResource Timeline1}"/>
</EventTrigger>
<EventTrigger RoutedEvent="FrameworkElement.Loaded"/>
</Window.Triggers>

Now I've got a nice passive FYI that there's an update.

image

I want to show an update button when the user visits the Options Dialog, which brings me to my awesome volunteer designer Felix Corke (blog). If you want a great WPF or XAML designer, give Felix money. Here's my original Option Dialog:

OldBabySmashOptions

And here's the Felix version:

image

Seriously. It hurts. Brings a tear to my eye.

When the user needs to update, I'll do two things. First, there will be a button that says UPDATE!

updatingoptions

Second, after they've hit Update there will be a Progress Bar and that will update as the new version is download in the background.

 optionsdialogupdating

The API is surprisingly easy to use. We check to see if we were launched from the Network, then I check again (really not needed since I did it earlier, but I like to double-check) for an update. This isn't asynchronous, but it's fast.

I setup two event handlers to listen to the UpdateProgress changing, and to get notification when the system has completed the download of the update. Then I fire off an asynchronous update. 

private void updateButton_Click(object sender, RoutedEventArgs e)
{
if (ApplicationDeployment.IsNetworkDeployed)
{
ApplicationDeployment deployment = ApplicationDeployment.CurrentDeployment;
if (deployment.CheckForUpdate())
{
MessageBoxResult res = MessageBox.Show("A new version of the application is available,
do you want to update? This will likely take a few minutes...",
"BabySmash Updater", MessageBoxButton.YesNo);
if (res == MessageBoxResult.Yes)
{
try
{
deployment.UpdateProgressChanged += deployment_UpdateProgressChanged;
deployment.UpdateCompleted += deployment_UpdateCompleted;
deployment.UpdateAsync();
}
catch (Exception)
{
MessageBox.Show("Sorry, but an error has occurred while updating.
Please try again or contact us a http://feedback.babysmash.com. We're still learning!",
"BabySmash Updater", MessageBoxButton.OK);
}
}
}
else
{
MessageBox.Show("No updates available.", "BabySmash Updater");
}
}
else
{
MessageBox.Show("Updates not allowed unless you are launched through ClickOnce from http://www.babysmash.com!");
}
}

The ProgressChanged event is really convenient because it includes the percentage complete! One less thing for me to do.

void deployment_UpdateProgressChanged(object sender, DeploymentProgressChangedEventArgs e)
{
this.updateProgress.Value = e.ProgressPercentage;
}

The Completed event is also fairly tidy (this one is simplified, and you could always use extra error handling. Note that since this was an asynchronous call, any exceptions that might have occurred elsewhere will show up here in the Error property of the AsyncCompletedEventArgs parameter.

void deployment_UpdateCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
{
MessageBoxResult res2 = MessageBoxResult.None;
if (e.Error == null)
{
res2 = MessageBox.Show("Update complete, do you want to restart the application to apply the update?",
"Application Updater", MessageBoxButton.YesNo);
}
else
{
MessageBox.Show("Sorry, but an error has occured while updating. Please try again or contact us a http://feedback.babysmash.com. We're still learning!",
"Application Updater", MessageBoxButton.OK);
}
if (res2 == MessageBoxResult.Yes)
{
System.Windows.Forms.Application.Restart();
}
}

I'll update this app to .NET 3.5 SP1 when it ships and I'll get a bunch of new features to make BabySmash! better like:

All in all, not much code for me to switch from an automatic ClickOnce Deployment that I had no control over to one I now have not only complete control over, but also one that fits in more nicely with our always improving UI. Also, an FYI, ClickOnce works with WinForms or WPF equally.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service

DasKeyboard - The Next Generation

July 31, 2008 Comment on this post [40] Posted in Reviews
Sponsored By

imageI feel like a ninja. A really loud, clicky ninja. This is a loud-ass keyboard. In the best way. I reviewed the original DasKeyboard two years ago, the one with totally blank keys, and let me tell you - if you want to learn how to touch type, type on blank keys. Plus, you can switch to Dvorak like some freaky people without missing a beat!

I'm a bit of a keyboard nut. I literally have nearly every Microsoft keyboard and mouse set ever made, and at least a dozen other brands. I'm always looking for THE keyboard, or at least THE keyboard du jour.

The new DasKeyboard is even clickier than the last one. It's a totally different redesigned keyboard and it's exquisitely and comfortably clicky. No way you'd be able sneak an instant message while on a conference call with this keyboard. If you like a quiet keyboard, just stop reading now. This is the Gregory Hines and Savion Glover of keyboards. This is STOMP: The Keyboard. (Ok, last one) This is "Bring in the Noise, Bring in the Keyboard."

yhst-40922258946781_2006_102649It's kind hard to talk about this keyboard without possibly sexually harassing the keyboard itself. It's solid, smooth and glossy and feels good to the touch. The keys are very well balanced and require less effort to press than the last DasKeyboard. There's something I can't quantify about this keyboard, though - Somehow I'm able to type about 10% faster on it. Sounds weird, I know, but it's true. I don't know if it's the "throw" of the keys (the distance they travel) or the smoothness, but my fingers get less tangled with it. Your mileage may vary, but typing on a DasKeyboard is like running downhill as a child. You have to just stop thinking about your feet (fingers) and just keep slapping away. However, as with running downhill, there's that moment when you think "how am I going this fast?" and then you trip over your feet (fingers.)

I prefer the blank version or "Ultimate" but there are two, the "Professional" has normal keys. Both have a USB2 hub on the side with two ports, which finally gives me Mac Keyboard parity, somewhere to plug in my mouse and a memory stick. It's got a SIX FOOT USB cable, so holding it in my lap while leaning back wasn't a problem.

The DasKeyboard is loud and wonderful and I recommend it. It's got a 30-day guarantee if you can't hear yourself think over the clicking. If you want to hear it, check out Frank Caron's review and the associated MP3 file.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service

July 2008 Technical Reading List

July 26, 2008 Comment on this post [28] Posted in Learning .NET | Musings
Sponsored By

IMG_0019I'm still using the Kindle every day for casual reading, but just now I noticed that my pile of technical books on my desk is taller than my son.

Actually, a few of these I've already read in manuscript form and I wrote either a foreword or a quote for good ones. The vast majority of the pile are books I'm currently wading through (slowly).

Here's the books I'm currently trying to read, as told by the Delicious Library application.

julyreadinglist

I've previously read Code Leader and Head First Software Development and provided quotes extolling the virtues of both, but they are such good books that I end up referring to them often enough that I haven't moved tem over to the shelf.

BTW: The Ian Griffiths/Chris Sells WPF book is in my bag. ;)

Related Links

What are you currently reading (technical books...we'll do fiction later)?

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service

Make your Website Mobile and iPhone Friendly - Add Home Screen iPhone Icons and Adjust the ViewPort

July 25, 2008 Comment on this post [18] Posted in ASP.NET | ASP.NET MVC
Sponsored By

If you're noticing when looking at your blog traffic logs that more and more people are visiting your site from a mobile device, you likely want to be accommodating.

I have noticed recently that mobile devices like the iPhone, iPod Touch and Danger Hiptop (well, that's probably just one guy) have been creeping up my list of Browsers+OSs that visit this blog.

image

How can I make their experience suck less? Just because the iPhone has Safari and can handle most full-size doesn't mean I should go bonkers with the HTML. There's a few simple things that can be done to make the experience more seamless.

Add Home Screen iPhone Icons for your Website

If you visit a website on an iPhone and hit the plus button and click Add to Home Screen...

NOTE: Hold down HOME and the LOCK button to take iPhone screenshots.

IMG_0004

You'll get this screen with a generated thumbnail icon of the current browser's screen. In this case, it's way too tiny and doesn't really well represent my site. It's certainly not an icon that I'd want on an iPhone's Home Screen.

IMG_0005

However, if you make a 60x60 PNG image file and name it "apple-touch-icon.png" and put it in the root of your website, you'll get control over that icon.

apple-touch-iconIf you don't have control over the root of your domain you can add a <link> to your pages and point it to whatever PNG you like wherever you like:

<link rel="apple-touch-icon" href="/customIcon.png"/>

Now, if you hit Add to Home Screen, you'll get a nice image with automatically rounded corners and a shiny bevel (the phone does that), your icon like this, will show up like this:

IMG_0007 IMG_0008

Very little effort for a considerable amount of polish.

Adjust the ViewPort for a "Pre-Zoomed" iPhone Experience

Next, if you visit a web page with Mobile Safari and you always double tap to select the content and zoom to the width of it, why not just set that as an initial default? Just add a <meta> tag like this:

<meta name="viewport" content="width=670, initial-scale=0.45, minimum-scale=0.45"/>

That will set the width of the "viewport" - the part of the page that is visible in the zoomed-in view - as well as the the initial zoom scale and minimum scale. This makes for a pre-zoomed and easily scrolled experience that doesn't change the way the page is laid out.

IMG_0003

It's still the full content, just pre-zoomed for the iPhone.

Enabling All Mobile Devices

Next, to the mobile users who are not using an iPhone, about two years ago I added support to DasBlog for a custom Mobile Theme that would enable Windows Mobile and Blackberry Mobile Browser users to browse DasBlogs more comfortably. In the DasBlog web.config there is a huge section at the end that was populated from this CodeProject article on BrowserCaps. It uses the older ASP.NET 1.1 style of browser detection.

dasblogblackberry

For example, if I wanted to serve a Mobile Theme to iPhone users that visit my blog, I could add these lines to the filter areas for platforms and OS's:

<case match="iPhone">
platform="iPhone"
</case>
...snip...
<case match="iPhone">
os="iPhone"
</case>
...snip...
<case match="iPhone" with="%{os}">
isMobileDevice="true"
</case>

DasBlog then just checks like this and does the right thing. DasBlog uses its own theming engine, but you can use this kind of detection and "downgrade" your site for any device you like.

//Are we on a Mobile Device? See if we have a mobile theme and use it instead.
System.Web.Mobile.MobileCapabilities mobile = (System.Web.Mobile.MobileCapabilities)Request.Browser;
if(mobile.IsMobileDevice == true)
{
theme = themes["mobile"];
if(theme == null)
{
loggingService.AddEvent(new EventDataItem(EventCodes.Error,
String.Format("If you have a theme called 'mobile' in your themes folder,
readers who visit your site via a Mobile Device will automatically
get that theme. User-Agent: {0}",Request.UserAgent),
String.Empty));
}
else
{
return theme;
}
}

Either way, if you choose to setup a custom Mobile theme for a visitor, or you just add a few bits of "chrome" like friendly icons and some browser specific metadata, it's important to at least be conscious of who is visiting your site in which devices and feel empowered to make good experiences for them.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.