the logo
Thanks for visiting my site. I am a president of Wildermuth Consulting Services, LLC in Atlanta, Georgia. I currently spend my days thinking far too much about the EDM, SQL Server 2008, database development, WPF, Silverlight, WCF, Entity Framework, Astoria and my forthcoming book "Prescriptive Data Architectures". Look here to see what else I am up to.

Rants

JavaFX Announced...

Silverlight Logo

JavaFX was announced at JavaOne this week.  What is it?  Its a RIA platform for creating compelling in-browser applications.  Certainly this looks like its a competitor for Flash and Silverlight.  Interestingly, instead of being able to write Java (at least from the quick look I had), it looks like they created a new script language (called JavaFX Script) for it.  Seems like a step backwards...but that's just me.

What it does have going for it that Silverlight doesn't is interoperability with NetBeans and tools for the Mac.  I don't think NetBeans interoperabilty is important, but tools for the Mac is IMHO.  What do you think?

Wednesday, May 07, 2008 |7 Comment(s) | (digg this)

Executing Code on the UI Thread in Silverlight 2

Silverlight Logo

With the asynchronicity question still dogging Silverlight 2, I thought I'd mention an oft forgotten little class in Silverlight (and in WPF) called the Dispatcher. Much of the confusion with asynchronous programming seems to stem from the fact that developers over complicate the problem.  Think that they need to handle the cross thread calls themselves. They tend to create two way communications for this or overuse the BackgroundWorker's ReportProgress functionality.

The key to simplifying calling the UI thread is the Dispatcher class.  This class supports a static (or shared) interface for executing code on the UI thread.  For example, you can call Dispatcher.BeginInvoke to invoke some arbitrary code on the UI thread:

// With Simple Lambda
Dispatcher.BeginInvoke(() => DoSomething());

// Also With Lambda
Dispatcher.BeginInvoke(() =>
  {
    DoSomething();
  }
  );

// or with Anonymous Delegate
Dispatcher.BeginInvoke(delegate()
  {
    DoSomething();
  } );

This is all is required to execute code on the UI thread.  The Dispatcher guarantees that this code is executed on the main UI thread. This is simplified versus the same WPF code. The Windows Presentation Foundation  uses a a prioritized message queue so that the Dispatcher really allows developers to not only make calls to the UI thread, but do so with some priority attached.  (See my MSDN article on the Dispatcher in WPF for a more detailed explanation). In Silverlight 2, the model is simplified (for better or worse). When calling the UI thread, you simply need to specify the code to call on the UI thread...the priority is gone.

Unfortunately there is no way currently to reliably test for the UI thread (again unlike in WPF where the DispatcherObject was part of the object hierarchy so you could call CheckAccess to see if you were on the UI thread). Because of this Silverlight 2 has a fundamental problem. It is unclear when we are on the UI thread. This is especially problematic for the event driven architecture that Silverlight 2 employs. This is exemplified by the fact that during some events (WebClient calls are especially prone to this behavior) seem to fail silently when you try and update the UI.  This is unlike the BackgroundWorker who throws an UnauthorizedAccessException (with the message of Invalid Cross Thread Access). So at times I find myself throwing in Dispatcher.BeginInvoke calls if the UI is failing to update in events (both control events and other events). This isn't a great solution but it does solve the issue much of the time.

I've attached a simple Silverlight 2 sample that shows this technique.  Let me know if you have any questions about this sample.

Tuesday, May 06, 2008 |1 Comment(s) | (digg this)

Brad Abrams' ASP.NET Providers Example

Silverlight Logo

I hate to just link other blogs, but this example from Brad Abrams is a biggie. In this entry he shows how to consume the ASP.NET Authentication, Profile and Role Providers from Silverlight 2 code. It is an impressive example and is well worth the time to dig into the code.

Monday, May 05, 2008 |Add Comments | (digg this)

Improved Version of Deep Zoom Composer Now Available

Silverlight Logo

The Expression team has released a new Beta version of the Deep Zoom Composer with a plethora of changes.  These include:

  • Better Exporting
  • Improved Design Experience
  • Better Collection Exports
  • Help Actually works.

If you're looking at Deep Zoom, this is a must have.

Saturday, May 03, 2008 |Add Comments | (digg this)

Adobe to open FLV and SWF formats

Silverlight Logo

In an interesting development that I can only assume means that Silverlight is having an impact on Adobe, they've decided to open and standardize their FLV and SWF formats so that anyone can build them.  Not only are they opening the formats but also removing licensing fees for mobile platforms.  Nice!

This is good news for Flash/Flex/AiR developers out there. In my opinion this also bodes well for Silverlight as it means that Adobe is taking the Microsoft platform as a serious competitor.

What do you think?

Thursday, May 01, 2008 |1 Comment(s) | (digg this)

Creating a Pseudo-Dialog with Silverlight's Popup Control

Silverlight Logo

Originally I had planned to start my screencast this week with a how-to on creating a sort of fake dialog window in Silverlight 2. Unfortunately I got the flu so I've decided to put off the screencast for another week but share with you how to create the fake dialog, but in full fidelity text and code examples.  If you cross your eyes, it looks like its even in 3D.

The cornerstone of creating a fake dialog in Silverlight 2 is the Popup control. The Popup control is a special container that when shown always shows up over other controls without taking up any space. For example, here is a simple Silverlight 2 app with a Rectangle and a Button.  In addition, we've added a Popup with a simple Grid inside it:

<UserControl x:Class="PopupFun.Page"
    xmlns="http://schemas.microsoft.com/client/2007" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    >
  <Grid x:Name="LayoutRoot" Background="White">
    <StackPanel Width="200" Height="200" VerticalAlignment="Top">
      <Rectangle Fill="Blue" Width="100" Height="100" />
      <Button x:Name="showButton" Content="Click Me" />
    </StackPanel>
    <Popup x:Name="fakeDialog">
      <Grid x:Name="theBack" Background="#80000000">
        <Grid.RowDefinitions>
          <RowDefinition />
          <RowDefinition Height="Auto" />
          <RowDefinition />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
          <ColumnDefinition />
          <ColumnDefinition Width="Auto" />
          <ColumnDefinition />
        </Grid.ColumnDefinitions>  
        <Border BorderBrush="Black" 
                BorderThickness="2" 
                Background="WhiteSmoke" 
                CornerRadius="15" 
                Grid.Column="1" 
                Grid.Row="1">
          <StackPanel Margin="8" Width="200" >
            <TextBlock TextWrapping="Wrap">
                This is just some sample text. It doesn't 
                matter what it says as long as it is long 
                enough to actually wrap
            </TextBlock>
            <Button x:Name="closeButton" 
                    Content="Close" 
                    VerticalAlignment="Bottom" />
          </StackPanel>
        </Border>
      </Grid>
    </Popup>
  </Grid>
</UserControl>

When we show the page initially, the Popup is hidden (because it's IsOpen property is false by default):

 

But when we change the IsOpen property (in the Click eevent of the Button),. the Popup is shown on top of the existing content:

 

What is particularly interesting about the Popup control is that it takes no space in whatever container it resides in.  The Popup control is meant to shown over the existing content. The problem is that you will want to take over the entire screen with the fake dialog.  In this case the size of the Popup won't cover the entire screen by default.  To fix this we can register for the Application's Resize event to change the size of the Grid (named "theBack") inside our Popup:

App.Current.Host.Content.Resized += (s, e) =>
{
  theBack.Width = App.Current.Host.Content.ActualWidth;
  theBack.Height = App.Current.Host.Content.ActualHeight;
};

This will resize the Grid whether the Popup is shown or now. Now that we have the resizing code in place, the dialog takes over for the entire screen:

 

There are a number of things you can do with a Popup control, but this should give you a quick primer on how the Popup control really works.  The source project can be downloaded at the link above.

Thursday, May 01, 2008 |3 Comment(s) | (digg this)

The Hard Part of Software Development

Silverlight Logo

I've spent a lot of time the last few weeks looking at some of the new buzz words in software development. Domain specific languages, dynamic languages, TDD, DDD, *DD, etc.. Most of these ideas have definite benefits to the work of software development but I think they miss the mark on what is really hard in software.

In most projects I've worked on the past twenty some-odd years, the hard part is not how to architect a project, not how to tune a database and not how to eke out every CPU cycle of a function call.  In fact the hardest part has always been in understanding how a business does business. There are many names for this but I like to think of this as domain specific knowledge. It's the time in the meeting room with the business veterans (stakeholders of one sort or another) that understand how it really works.  Whether that is how freight is shipped across country, how users register with forums or how those scanners at the grocery stores actually work; in all cases these stake holders already know how they do or want to do their job.  It is our work as developers into transitioning that into actual software.

Eric Evans talks about this in his Domain Driven Design book, but I think some readers of his book seem trapped into thinking that the magic of the domain is the top-down design of a system.  In my opinion they are missing the point.  Turning domain knowledge into a system is hard work, no matter what design methodology you use.

It's a people problem. We engineers talk in terms of code, architecture and data.  We have our private language that helps us communicate.  If you don't think that's true, ask your spouse/partner what happens when they hear you talk about work with your friends. The thing is that in most industries this is true. When you talk to stake holders, they have their own language too. Our job is to pull that information from them and translate it into software designs. Often a small misunderstanding can be the cause for large changes in a system. Getting this knowledge transfer right is crucial.  For the most part we do an admirable job of it, but I think it is critical to understand how essential this is. Constant communication with the eventual users of a system is a key to the long-term success of any project.

So, if you've stayed with me this far we're probably in agreement about the importance of domain knowledge. Here's where I get incensed. So much of development these days is being done by outside developers.  The strategy of business to keep developers around has vanished. This is evidenced by off-shoring, outsourcing and contractor-based development. Companies are attempting to cut costs by using cheaper developers as well as development teams they can cut loose once a project is complete. 

The problem with this strategy is that all the domain knowledge is leaving the enterprise. Companies spend a lot of money for a project and some percentage of that money is in teaching the development team about the problem domain and the way that the company does business.  By having short-term development strategies all this knowledge isn't being recouped by the companies. I don't think they understand yet what a bad deal this is for them.  But it's not just bad for companies, it is also bad for developers.

In some sense we developers are part of the problem. Quitting your $75K/yr job to be hired back at $75/hr seems like a good deal, but in fact it is not a good deal for either party.  Your loyalty is to the paycheck and when you leave, the domain knowledge goes with you. This extra knowledge can help if you stay in the same industry but that's pretty rare.  Usually you go to a new type of company and spend time 'ramping-up' on how they do their business. This seems bad for developers because most of the ones I know have passion for technology. They want to be part of a winning team. By being a well-paid mercenary it becomes easy to not care about what you are doing.  At the end of the contract you just move on, forcing you to divest in a personal stake. I miss that part of this business.  I have had more enjoyment about projects that didn't work than all the mercenary positions I've ever held (yes, I am looking at you Gen<X>).

The dirty little secret in my house is that I'd give up my business and go work for a company if I could believe in them and believe that I was part of something special.  In some ways I think most developers are like that. But in this atmosphere of short sightedness, it just doesn't exist.

So do I have a call for action?  No. I think that domain knowledge is an important idea that both developers and companies need to address, but I don't have a nice and tidy solution. This is a shift that I think has to happen in software development. Both sides of the table need to look long at the last five to ten years and determine if what we're doing now is better than before.  Does it only feel better because each line of code is cheaper to produce (mostly a product of better platforms, not better coders). I hope this can change.

UPDATE: Here's an interesting link that has a different opinion of this subject:

http://thedailywtf.com/Articles/Up-or-Out-Solving-the-IT-Turnover-Crisis.aspx

Wednesday, April 23, 2008 |11 Comment(s) | (digg this)

New Silverlight Tour Stops!

Silverlight Logo

With the success of our first two Silverlight 2 Workshops, the Silverlight Tour is expanding to three new cities and more stops.  The new cities are:

  • New York, NY
  • Denver, CO
  • San Diego, CA

We've also expanded our schedule out to the end of the year.  We'll be returning to Seattle and Dallas. Don't miss out on three days of Silverlight 2 training in a city near you.

Monday, April 21, 2008 |Add Comments | (digg this)

Reading Silverlight Embedded XAML

Silverlight Logo

I was talking with Walt Ritscher (of VB MVP fame) recently and he noted that he was trying to find a good way to grab XAML out of the assemblies in Silverlight 2. While Walt got a great answer from his brethren at Wintellect, I wanted to point out a quick way of reaching into the project to get the XAML

One thing I noted was that I knew that the Silverlight 2 template reached into the assmebly to get the XAML at runtime so that code had to be there.  And it is there.  Its there in the 'codegen' class for every XAML based class (e.g. Page.xaml and other user controls). To get there easily, go to your Page.xaml and find the InitializeComponent call and press F12 to open that method.  This will open up the Page.g.xaml (the generated partial class). This leads us to this code:

public void InitializeComponent()
{
  if (_contentLoaded)
  {
    return;
  }
  _contentLoaded = true;
  System.Windows.Application.LoadComponent(this,
    new System.Uri("/SeeMyXaml;component/Page.xaml", 
                   System.UriKind.Relative));

  this.LayoutRoot = ((Grid)(this.FindName("LayoutRoot")));
  this.theXaml = ((TextBlock)(this.FindName("theXaml")));
}

Note the LoadComponent call.  It specifies a Uri to load the XAML right there is our project all along! 

So what can we do with it?  I've crufted up a simple project (link provided above) that reads the XAML with a XDocument class then spits it out (with formatting but not coloring) in a TextBlock.  The code is dead simple:

// You may need to add System.Xml.Linq reference to get 
// the XDocument class
XDocument doc = XDocument.Load("/SeeMyXaml;component/Page.xaml");
theXaml.Text = doc.ToString(SaveOptions.None);

You should notice that we're using that same path syntax to get the Page.xaml from the embedded resource. Simple, huh?

Tuesday, April 15, 2008 |Add Comments | (digg this)

Silverlight Policy Snippet and Intellisense

Silverlight Logo

Over at Tim Heuer's blog, he has a great article and download to get a new Snippet to create Silverlight Policy files.  If you are doing any Silverlight 2 work with Web Services, its a must install AFAIAC.

If you don't know, Tim recently joined the Silverlight Evangelism group (with Laurence Moroney, Adam Kinney, Jesse Liberty, et al.).  If you're interested in Silverlight, this is a blog you should definitely subscribe to.

Monday, April 07, 2008 |1 Comment(s) | (digg this)

Meetup in Seattle

Silverlight Logo

I decided to have a quick meet-up of some of my Twitter contacts in Seattle this week.  I figured I should open it to anyone else who wants to show up.  Follow the GeekDinner link above to RSVP so I can tell the bar to make room.  Let me know if you have any questions about the dinner!

Note: GeekDinners isn't perfect yet but after I get back from Seattle I will be doing some improvements to the site to make it a bit easier to use. If you want to volunteer let me know.

Monday, April 07, 2008 |8 Comment(s) | (digg this)

HtmlWindow.Navigate and enableHtmlAccess

Silverlight Logo

Adam Kinney (of Silverlight Evangelism fame) was finding some odd behavior with his new (and cool) Silverlight Powered XBox Gamercard. Of interest was the Gamertag link on the Gamercard. When you use it on his site, it works like a dream but once you put the Gamercard on a separate site the link would cause the Silvelright app to just disappear instead of navigating to XBox.com.  

One note, Adam figured it out...not me.

So what is going on.  Adam noticed that it worked on his site unless the subdomain was different (it was working on www.adamkinney.com but not adamkinney.com). It turned out that the issue was that enableHtmlAccess was not enabled.  This is a great case where Adam should have used HtmlPage.IsEnabled.  In case you're not aware, the HtmlPage.IsEnabled returns true if the Silverlight application has the right to deal with the HTML page.  But how is this determined?

There are three ways to host Silverlight today:

  • <object> tag
  • Silverlight.js
  • <asp:Silverlight /> control for use on ASP.NET 3.5 AJAX pages

For Adam's needs he was using the <object> tag so that people could drop it on their blog and it would just work. By default enableHtmlAccess is false when using the <object> tag hosting method. So the fix for Adam's problem was to add this parameter to the object tag.  Go look at the Silverlight Gamertag toy if you want to see how that works.

The real issue here is consistency.  I assume Adam has worked with Silverlight like I have.  Lots of small to medium sized examples.  Examples are cool but generally that means we've been creating Silverlight content but using the most simple method for hosting our examples.  This means the asp:Silverlight control. This wasn't obvious to either of us though because in both the Silverlight.js and <asp:Silverlight /> hosting method the enableHtmlAccess defaults to true...which is opposite of the <object> method.

So the lesson learned here is to use HtmlPage.IsEnabled to test to see if your particular host allows access to the HTML of the page (including support for HtmlWindow.Navigate).

HTH

Saturday, April 05, 2008 |3 Comment(s) | (digg this)

Adam Kinney has a new SIlverlight-based XBox Gamercard

Silverlight Logo

Adam Kinney has created a new Silverlight 2 Application to show off your XBox Gamercard on your site.  I like his design and it is not static so it shows what you're doing at any specific time.  What do you think of mine:

Get Microsoft Silverlight

Do you like?

Thursday, April 03, 2008 |4 Comment(s) | (digg this)

Silverlight Compatibility Confusion...

Silverlight Logo

While reading through the Silverlight Runtime system requirements, I found two important (but under reported) limitations:

While I understand the Windows 2000 limitation.  Back porting the Silverlight 1.0 makes sense to me. But I hoped some of my Apple-savy readers (if I haven't pushed them all away) could tell me whether the PowerPC story matters.  Will non-support for Silverlight 2 matter to PowerPC Mac OSX users?

 

Thursday, April 03, 2008 |Add Comments | (digg this)

Silverlight 2 Bugs and Issues

Silverlight Logo

As I've been neck-deep in Silverlight 2 for a couple of months now I noticed that there are some bugs/inconsistencies that aren't necessarily known to everyone. Here's a list of some of the issues (with workarounds if possible):

Custom Control Data Binding

If you are writing User/Custom Controls that want to be used in data binding (i.e. DataTemplate), you must use the assembly name in the namespace declaration, even if it is in the main assembly:

Bad:
xmlns:my="clr-namespace:MyAssembly.Controls"
Good:
xmlns:my="clr-namespace:MyAssembly.Controls;assembly=MyAssembly"

This is a known bug that will be fixed in future builds.


Uri Issues

In Silverlight 2 (in contrast to previous versions) the assets are packaged up in a .xap file.  This .xap file is simply a ZIP file that contains the assemblies and other assets.  In this file you can have images, fonts and other assets required.  This new facility has made Uri's a bit confusing.  When you specify a relative Uri in your Silverlight 2 project it may mean inside the .xap file or it may mean from the server. 

The key is that relative Uri's will first look in the .xap file then look on the server but this isn't universal.  For example if you have a foo.jpg in the root of your .xap file and specify this Image tag, it will find it in the .xap file:

<Image Source="foo.jpg" />
 

If the foo.jpg doesn't exist in the .xap, Silverlight 2 will look at the server for the file (most of the time)...but where is it looking?  Unlike what you might expect, it actually looks on the file server relative to the ClientBin directory (where the .xap file is loaded from).  If you want to have an image file loaded from the /image folder of the web server you would specify:

<Image Source="../images/foo.jpg" />
 

This works because it is relative to the ClientBin directory.  If you specify "/images/foo.jpg" it won't look on the server.  This is the bug.  Using a full path to the server fixes this but that is fragile (you need to change it when you deploy an application).

This is especially an issue with MediaElement as it doesn't seem to work at all with relative paths.  Interestingly if you look at the Uri usage with Reflector, the Source property in the MediaElement strip off the Uri and just send it the plain string (again, this is what I consider a bug). So if you're using a MediaElement, use non-relative paths for the Source.

In general I have found different/buggy behavior with different controls so if you are having trouble with Uri's, go to non-relative Uri's (e.g. full paths).


Using the Silverlight Control

 If you want to use the ASP.NET Silverlight Control it requires ASP.NET AJAX 3.5.  It requires a ScriptManager on the page and only works with the 3.5 version of AJAX. This means that if you are not using AJAX 3.5 you will need to use one of the other methods:

I tend to like the Silverlight.js for deployed projects anyway because of the additional functionality of Silverlight.isInstalled and other small features.  If you used Silverlight 1.0 you'll  already be familiar with Silverlight.js.  The version that ships with Silverlight 2 has been updated to support Silvelright 2 deployment.


ImageBrush Can't Be Data Bound

This is a small but pesky bug that if you try to use data binding with the Image brush it just fails (or locks up the browser).  So if you want to set the ImageBrush, you'll need to wrap a UserControl and data bind a DependencyProperty that will set the ImageBrush manually.  Not hard but just a workaround.


LINQ Projections or Anonymous Types Fail on Data Binding

If you are using LINQ to do projections or using Anonymous types, data binding gets confused and tends to lock up the browser.  For example:

var qry = from x in customers
          select new
          {
            Name = x.CustomerName,
            Phone = x.ContactPhone
          };

theList.ItemsSource = qry.ToList();

The alternative is to just select the entire object (or use static types instead of anonymous types).


Popup.DataContext Doesn't Work

If you are using the cool Popup element and you want to use Data Binding to fill in data, the DataContext of the Popup fails to propogate its container.  Therefore you need to manually set the first child's DataContext instead:

<Popup DataContext="{Binding}" /> <!-- Doesn't Work -->


That's all for the issues that I am working around these days.  If you have more, feel free to drop them in the comments!

Monday, March 31, 2008 |2 Comment(s) | (digg this)

Not Sure the Copy Bug in Gone in Vista SP1

I am copying a video file across my wireless network (though this particular machine is kinda flaky, so it might not be Vista's fault) but I thought this was funny:

 

Sunday, March 30, 2008 |3 Comment(s) | (digg this)

Atlanta Code Camp 2008 Presentation Slides and Demos

Silverlight Logo

As promised here are the slides and demo's from my talks at the Atlanta Code Camp yesterday. It was a great time and I got to see a lot of attendees and speakers who I haven't seen in a while. 

My big embarrassment moment was at the speaker's dinner when I saw David Silverlight and completely forgot who he was (i've met him a number of times).  When I heard he'd just flown in from Florida, I asked him, "Did you fly in with David Silverlight?".  He promptly replied, "In a sense, yes..."  I was so red faced. 

On to the slides and demos:

Enjoy!

Sunday, March 30, 2008 |Add Comments | (digg this)

Speaking at the Atlanta Code Camp

Atlanta Code Camp Logo

This weekend I will be at the Atlanta Code Camp this Saturday. I have four talks and they follow the predictable Silverlight and Data topics. Here are the talks:

  • Using Blend 2.0 for Silverlight
  • Consuming Data with Silverlight 2
  • Digging into Deep Zoom
  • Using C# 3.0 Features for Clean Code

In addition, we giving away a seat at the upcoming Atlanta stop of the Silverlight Tour (on May 12-14th, 2008).  Com early and state late to be there for the drawing.  The code camp is giving away a number of prizes, this is just one of them.

Hopefully, i'll see you there!

Wednesday, March 26, 2008 |Add Comments | (digg this)

Results of the Data Access Poll

If you havent voted, please feel free to vote for what data access strategy here:

http://adoguy.com/2008/03/21/Data_Access_Strategies.aspx

For those who were interested in the results:

Web Poll Powered By MicroPoll

One thing that I took away from this is that some strategies did not get any votes (and I expected them to) like CSLA.  I think that's a product more of the fact that Rocky's readers probably don't read my blog...so the poll is very unscientific.  I was surprised by the sheer number of LINQ for SQL respondents and the big Entity Framework numbers.  Both being new technologies, I didn't expect there to be much usage yet.  Go figure.

Wednesday, March 26, 2008 |Add Comments | (digg this)

Few Seats Left for Silverlight Tour - Seattle

Silverlight Tour Logo

If you are interested in attending the upcoming Silverlight Tour stop in Seattle on April 9-11th, there are only a handful of seats left.  Be sure and sign up soon.  We only accomodate sixteen students per class to make sure everyone can get the attention they deserve.

Wednesday, March 26, 2008 |Add Comments | (digg this)

Silverlight SeeqPod Player now Silverlight 2 (with SourceCode)

Silverlight SeeqPod Screen Shot

In my weekend attempt to upgrade some of my older examples, the Silverlight SeeqPod Player is now all Silverlight 2

Converting the Silverligth 1.1 application to a 2.0 was remarkably harder than the Silverlight 1.0 to 2.0.  It may be because of use of user controls versus real controls (I changed from using two nested user controls to using a ListBox with Control Templates). In addition, switching the format of the web service usage from consuming XML directly to using DataContracts confused it a bit but overall it wasn't difficult. Lastly, I was using a layered HTML input control for a TextBox, and changing it over to a built-in one, took a little time too. Some code just simply disappeared (as I was moving some text around to make it appear like it was centered, but now its just a matter of marking it as TextAlignment = Center.

I was also able to polish some features I wanted to add:

  • The Play Panel how slides in and out like I originally wanted.
  • When the URL from SeeqPod is a dead link, I now change the UI to show its a bad song so you don't continue to click on the song.
  • I also added Tooltips to help make sense of some of the non-text buttons.

Here's the source if you want to play with it: Source Code

UPDATE: I've updated the code (and the app) as I found some odd behavior with random or shuffle play.  One of the things I noticed was that the selected item was not getting updated all the time.  I realized that during some operations (MediaElement specific events and callbacks in Web Service Proxy's), you're not actually running on the main UI thread.  This is not a big surprise but since it fails silently it can cause odd issues.  To get around it I used the Dispatcher to fire an event on the UI thread:

Dispatcher.BeginInvoke(() => { songList.SelectedIndex = someValue; } );

You could use an anonymous delegate, but I prefer this shorthand Lambda function.  It fixed the issue with the wierdness of showing hte selected index. 

Hope this helps some of you struggling with issues.

Sunday, March 23, 2008 |3 Comment(s) | (digg this)

My Silverlight Page now using Silverlight 2

Silverlight Spotlight

Its not a dramatic change, but I've ported my Silverlight 1.0 Silverlight page to use Silverlight 2.  There were some interesting lessons learned:

  • If I want to use the ASP.NET Silverlight control, I have to upgrade to ASP.NET AJAX 3.5.  Not a big deal but annoying.
  • If you used class-style JavaScript, it came over to C# pretty easily.  (Can't same the same for VB though).
  • I was able to switch from Dynamic XAML to Data Templates (with a ListBox) very easily.
  • There are some font rendering changes as the old XAML that used to fit on the template now overlaps.  Had to do some editorial changes to accomodate the change.
  • There is a bug in ListBox that does not reset the position of the ListBox's Scrollbar if the number of items changes (e.g. changed the ItemsSource).  Doing hacks like ScrollIntoView() doesn't seem to fix it.  If you move it with the mouse it heals itself.

I've decided to release the code this time.  You can download it here: Source Code

Overall it was a fun little task.  Tomorrow I am going to port my SeeqPod player from Silverlight 1.1 to Silverlight 2 to see what can be learned there.

Saturday, March 22, 2008 |1 Comment(s) | (digg this)

Converting ASP.NET 2.0 to 3.5 for sites that use Silverlight 1.0

Silverlight Logo

Quick fix for a problem that was haunting me today:

If you upgrade an ASP.NET 2.0 app to 3.5 and have .xaml files in your project that are part of a Silverlight 1.0 or 1.1 project, the conversion wizard converters them to Build-type: "Page" and adds a custom build for building the WPF files.  If this happens you'll get a cryptic error:

"error MC6000: Project file must include the .NET Framework assembly 'WindowsBase, PresentationCore, PresentationFramework' in the reference list."

Go through your xaml files and mark them as "Content" and remove any custom tools and it will fix it.

Saturday, March 22, 2008 |Add Comments | (digg this)

Great Dissection of DeepZoom (and Constrast to Competitors)

Silverlight Logo

Jon Galloway has a new blog entry where he discussed and dissects DeepZoom. He explains it better than most and is really worth a read.  Of particular interest is the comparison with other technologies (e.g. Google Maps, Zoomorama, etc.).  He really makes some key points to explain why this is important to the Silverlight platform.  If you care about Silverlight, read it now.

Saturday, March 22, 2008 |Add Comments | (digg this)

Creating Linkable Silverlight Applications

Silverlight Tour

I've been teaching my students to be careful not to create Silverlight projects that alienate users and break the basic working of the web.  One of the things I've explained is that you need to make it so that the back button and links work (where applicable) in your applications. I haven't had a good example to show them until now.

I've created a quick and dirty example of how to change the address bar (and respond to this change when you return).  The trick to getting this to work is to use the HtmlWindow's CurrentBookmark and NavigateToBookmark members.  For example, in the example I have a ListBox that changes some state in my app.  When the SelectedIndex changes, I use NavigateToBookmark to change the Url:

theList.SelectionChanged += (s, e) =>
  {
    if (theList.SelectedItems.Count > 0)
    {
      siteInfo.Visibility = Visibility.Visible;
      siteInfo.DataContext = theList.SelectedItem;
      Site site = (Site) theList.SelectedItem;
      HtmlPage.Window.NavigateToBookmark(string.Concat("id=", site.Id));

      // HACK to fix non-binding of NaviateUri
      theLink.NavigateUri = new Uri(site.Url);
    }
    else
    {
      siteInfo.Visibility = Visibility.Collapsed;
    }
  };

Then in my app, on Load I look at the CurrentBookmark so that if I've returned to my application with the Bookmark specified, I can change the state of my app back:

this.Loaded += (s, x) =>
  {
    // Show current item if included in bookmark
    if (!string.IsNullOrEmpty(HtmlPage.Window.CurrentBookmark))
    {
      string[] parts = HtmlPage.Window.CurrentBookmark.Split('=');
      if (parts.Length == 2)
      {
        int id;
        if (int.TryParse(parts[1], out id))
        {
          Site selected = sites.FirstOrDefault(e => e.Id == id);
          theList.SelectedItem = selected;
        }
      }
    }
  };

This is enabling both the Back button as well as Linking to my app.  You can download the source here:

http://adoguy.com/downloads/backenabledsilverlight.zip

Or see a live version of it here:

http://www.silverlightdata.com/backenabledsilverlight.aspx

One caveats on the example:

  • When you return to the page with a bookmark, the ListBox selection isn't showing.  This is a ListBox bug that has been communicated to Microsoft.  It has nothing to do with this code.

 

Friday, March 21, 2008 |3 Comment(s) | (digg this)

View More Rants...