The Wonders of Technology

As many of you know, I am a vocal proponent of Media Center technology, having powered my home entertainment center with a Windows Media Center for several years now. A natural pairing to the Media Center technology is the ESPN 360 service.

Being a Florida Gator fan living in northern New England, it can be difficult to catch all of my team’s football games each season. Unless they’re playing a nationally telecast game, and if there isn’t a Big 10 team playing somebody, there’s a good chance it won’t be aired up here. Satellite is an option, but has obvious drawbacks, and while I tried getting together with the regional Gator Club, driving into Boston from New Hampshire every Saturday was just a little unwieldy.

When I first moved up here in 1998, I used to drive into the office on Saturday’s so I could listen to the game on Internet Radio using the work connection, which was substantially better than the dialup available out of my home. Then DSL became available and I was able to listen from home. Now, a short 10 years later, I am not only able to listen to the games from home, I now watch the video streamed over the Internet with the ESPN 360 service. The video is powered by Move Networks Media Player, and all things considered, the video quality is fantastic. (Incidentally, it looks like Microsoft just made an investment into Move Networks, which may lead to a Silverlight experience…)

ESPN360 Screenshot

ESPN360 Screenshot

There is one caveat to this service. A few years ago, the video was available for a paid annual subscription to ESPN’s GameCast online. ESPN abandoned that model in 2007, moving content to the “free” ESPN 360 service. I qualify the phrase “free” because the service is only available once they validate who your ISP is. When I first discovered this, I was using Comcast Cable for my internet access, and 360 was not available. I contacted Comcast, and was told that the qualifier for an ISP was not a bandwidth check, but rather whether the ISP had or had not paid ESPN for the privilege of carrying 360. Instead of a hit-or-miss individual subscription model, ESPN went with a model where the ISP was charged a high amount of money. (This is further validated by the fact that I verified the service was not available from the T1 Internet connection at my office – supplied by Verizon.) In my opinion, the Internet is not supposed to work that way…sites aren’t supposed to care who my current ISP is – just that I have a connection. </rant>

Also, I wonder why nobody has made a plugin to the service for the Windows Media Center. Maybe if I get some spare time this season, I may make a few phone calls and see if I can prototype something. Until then, I just close the MCE application and launch Internet Explorer in full-screen mode.

All that said, I have to pause and admire that in 10 short years, I went from not being able to watch over 60% of my favorite team’s games each season to being able to watch every game from the comfort of my living room. I wonder what another 10 years will bring…

Problem When Using a WinFormsHost in a WPF Popup Control

A colleague of mine recently sent this puzzle my way. Code reuse suggested he use a WinForms TreeView control inside of a WPF popup. The general UI principle here was similar to that of using a ComboBox, but instead of a list, a tree view would be shown in the popup.

The simplest XAML to reproduce the problem is as follows:

<Popup x:Class=”AWOLTree.WinFormsTreePopup”
  PopupAnimation=”Scroll” Placement=”MousePoint” StaysOpen=”False” AllowsTransparency=”False”>
      <wf:TreeView x:Name=”winFormsPopupTreeView”/>

What ends up happening is that the tree gets rendered, but any attempt to interact with the tree results in the popup closing. </setup>

So it was time to dig into the mystery. Why was the popup closing (or the most sensible hypothesis…why did the popup think it needed to close?) My first choice here would have been to use the new VS 2008 .Net source code debugging. However, I have installed .Net 3.5 SP1, and unfortunately the related symbols have not yet been posted (damn my early adoption…)

Instead, it was time to go back to Plan B – Reflector, which is now being published by Red Gate after many years of stellar stewardship by Lutz Roeder.

The MSDN documentation for the Popup control states:

When you set this property [StaysOpen] to false, the Popup content window has mouse capture. The Popup loses mouse capture and the window closes when a mouse event occurs outside the Popup window.

So, odds are that the issue has something to do with Mouse Capture. Sure enough, in the sequence of events, OnLostMouseCapture is one of the last (obvious) overrides called before OnClosed. So I popped open the default implementation of OnLostMouseCapture and found the following:

 private static void OnLostMouseCapture(object sender, MouseEventArgs e)
  Popup popup = sender as Popup
  if (!popup.StaysOpen
    PopupRoot reference = popup._popupRoot.Value
    if (Mouse.Captured != reference)
      if (e.OriginalSource == reference)
        if ((Mouse.Captured == null) || !MenuBase.IsDescendant(reference, Mouse.Captured as DependencyObject))
          popup.IsOpen = false;
(remainder omitted for clarity)

I put in a handler to check teh value of Mouse.Captured, and found that when a WinForms control inside of the popup was selected, it returned null, which falls directly into a call to popup.IsOpen = false, effectively closing the popup. Clicking on a WPF control inside of the same popup results in a valid reference being returned, explaining the difference in behavior.

Now what?

I see a few options. First, the code in question (which I was familiar with) could have been refactored to act on either a WPF or WinForms tree control, maintaining most of the desired reuse. Alternatively, there may be a way to work within the WPF framework to handle this special case, but I prefer to wait until I have .Net source debugging available again before looking at this option.

The Series Has Landed

With all due respect to Matt Groening, et al…

Okay. It took a little longer to get to this point than I had wanted it to, but the important thing is that I got here. What follows is hopefully a collection of a few things, including:

  • Solutions to technical problems that interest me that I either encounter directly or that have been brought to my attention by others;
  • Random rants (I seem to be prone to these) ;
  • Other odds and ends…

Basically, your typical Blog fare. I have been participating in the .Net community for several years now, mostly as an audience member (sometimes an excessively vocal one, but an audience member nonetheless.) It is time to start paying it back.

At a minimum, I intend to make it fun…