| Comments

This is part 6 in a series on getting started with Silverlight.  To view the index to the series click here. You can download the completed project files for this sample application in C# or Visual Basic.

We now have a functioning application but could use some more polish.  Let’s make the data template for the search results look a little better.  We’re going to modify a few things in the data template in Search.xaml for the ItemsControl. 

These modifications can be done in Blend just like we have been doing with the editing template features.  This is how it was accomplished above.  With these styles now applied the new UI looks like this:

Styled results

Notice how more polished that looks and we didn’t affect any code, just the template style.  Since there was a few changes here since the last step it would be a lot of code to write out but let me point out where the styles are in the final project.

The styles and templates are applied just like the binding syntax with data and the templates.  If we look at the ScrollViewer it now states:

   1: <ScrollViewer Style="{StaticResource scrollViewerStyle}" ...
   2: ...

Notice the familiar syntax?  instead of {Binding} it uses {StaticResource} to refer to a resource that either exists in the document or the App.xaml.  In this case the style is in the App.xaml (look for the scrollViewerStyle and scrollBarStyle nodes at the bottom of the file).

We also just made some subtle changes to the colors of the included style from the template.  With styling and templating in Blend, you don’t have to worry about modifying your .NET code most of the time.  We are able to change the visual layout and theme of controls without changing the code.

More resources on using Expression Blend:

Having a designer friend at this stage of polishing the UI is extremely helpful.  In fact, you’d likely have this UI defined MUCH earlier in the project than our exercise here.  The two tools, Expression Blend and Visual Studio, share the same project structure file so you can easily open the project in either tool instead of passing around loose files.

Take a look around the Assets/Styles.xaml file in the completed project to understand how styles and templates can be used.

Next step: finishing off our application by making it available out-of-browser in part 7.

| Comments

This is part 7 in a series on getting started with Silverlight.  To view the index to the series click hereYou can download the completed project files for this sample application in C# or Visual Basic.

In our final stage of this getting started series, we are going to make our application available for installation outside of the browser.  The steps are much simpler than you think.

Create the manifest

Using Visual Studio, right-click on the Silverlight application’s project and choose properties.  You’ll see a dialog box come up – notice the checkbox about Out-of-browser settings:

Application properties

When you click that you’ll be greeted with options to complete:

Out-of-browser settings dialog

These settings are important to provide visual information about your application when installed and running out of the browser.

  • Window Title – what is displayed in the window chrome for the app
  • Width/Height – the starting width and height of your application when launched
  • Shortcut name – the name for the desktop/start menu shortcut
  • Download description – a description of the application
  • Icons – must be PNG and must be included in the project marked as Content

Once you have all those in place your app is enabled for out-of-browser capabilities.  Let’s add an install button for your users in the navigation area in MainPage.xaml in the StackPanel called LinksStackPanel, add this XAML:

   1: <Rectangle x:Name="Divider3" Style="{StaticResource DividerStyle}"/>
   2: <HyperlinkButton x:Name="InstallLink" Style="{StaticResource LinkStyle}" 
   3:                  Content="install" Click="InstallOffline"/>

Now in MainPage.xaml.cs write the function for InstallOffline:

   1: private void InstallOffline(object sender, RoutedEventArgs e)
   2: {
   3:     if (Application.Current.Install())
   4:     {
   5:         InstallLink.Visibility = Visibility.Collapsed;
   6:     }
   7: }

You can see that after we check for a successful install, we hide the install button as it isn’t needed anymore.  What we need to do though is make that more dynamic in that it automatically knows to do that.  Additionally we don’t want the install button to show if the application is launched out-of-browser to begin with.  Luckily we have an API with a few properties that will help us out: InstallState and IsRunningOutOfBrowser.  Let’s make use of both of these.

Detecting InstallState and IsRunningOutOfBrowser

In the MainPage.xaml.cs file, we’re going to add an event handler to detect the change of our installation state of our application as well as a loaded event handler:

   1: public MainPage()
   2: {
   3:     InitializeComponent();
   4:     Loaded += new RoutedEventHandler(MainPage_Loaded);
   5:     Application.Current.InstallStateChanged += new EventHandler(OnInstallStateChanged);
   6: }

In that method we’ll check the various states to determine if our InstallLink should be visible or not (as well as the last divider):

   1: void OnInstallStateChanged(object sender, EventArgs e)
   2: {
   3:     switch (Application.Current.InstallState)
   4:     {
   5:         case InstallState.InstallFailed:
   6:             break;
   7:         case InstallState.Installed:
   8:             ToggleInstallLinks(true);
   9:             break;
  10:         case InstallState.Installing:
  11:             break;
  12:         case InstallState.NotInstalled:
  13:             ToggleInstallLinks(false);
  14:             break;
  15:         default:
  16:             break;
  17:     }
  18: }
  19:  
  20: void ToggleInstallLinks(bool hidden)
  21: {
  22:     InstallLink.Visibility = hidden ? Visibility.Collapsed: Visibility.Visible;
  23:     Link3.Visibility = hidden ? Visibility.Collapsed : Visibility.Visible;
  24: }

Now in the Loaded event handler we’ll check to see if the application is running out-of-browser or not:

   1: void MainPage_Loaded(object sender, RoutedEventArgs e)
   2: {
   3:     if (App.Current.IsRunningOutOfBrowser)
   4:     {
   5:         ToggleInstallLinks(true);
   6:     }
   7:     else
   8:     {
   9:         if (App.Current.InstallState == InstallState.Installed)
  10:         {
  11:             ToggleInstallLinks(true);
  12:         }
  13:     }
  14: }

Using these two APIs we can now automatically change our UI to hide functions not needed.

Detecting network changes

If our application doesn’t have network access, we shouldn’t allow the search to run because it may not have the capability of finding the Twitter search API.  There is an additional API for NetworkInterface that we can use to detect this.  We’ll do this in our Search.xaml.cs page by first adding an event handler in the constructor after our Loaded event handler line:

   1: NetworkChange.NetworkAddressChanged += new NetworkAddressChangedEventHandler(OnNetworkChanged);

This raises an event when the network status has changed.  Now in the OnNetworkChanged event handler we’ll check to see if the network is available and, if it isn’t, disable searching capabilities until it is:

   1: void OnNetworkChanged(object sender, EventArgs e)
   2: {
   3:     if (!NetworkInterface.GetIsNetworkAvailable())
   4:     {
   5:         // network may not be available, halt searching
   6:         SearchButton.IsEnabled = false;
   7:         SearchButton.Content = "DISCONNECTED";
   8:         _timer.Stop();
   9:     }
  10:     else
  11:     {
  12:         SearchButton.Content = "SEARCH";
  13:         SearchButton.IsEnabled = true;
  14:         _timer.Start();
  15:     }
  16: }

This is only an example of course, and you could provide other UI hints such as status indicators, etc. but for our application this should work now.

NOTE (Here be dragons): Simply checking for GetIsNetworkAvailable doesn’t guarantee in all circumstances that the Internet is not available.  Due to various ways corporations configure proxy servers and local IP addressing it is always good practice to have a fallback mechanism if you need to verify WAN Internet access.  This can be done by simply doing a WebClient request for a file on the web server – if the request succeeds you have Internet access, otherwise you may not.

You can find out more information about Out-of-browser experiences here:

Out of browser updates

You may be wondering how to trigger updates to an application if it was installed on to the machine.  There is an API that a developer can use called CheckAndDownloadUpdateAsync which triggers the update model.  The update model is outlined here.  Even though that article has a different API, the model of updating is the same *after* that method above is called.

Summary

Now we’ve taken our application from a blank slate to a working application with data and that can be installed out of the browser.  I hope this has been a helpful exercise to walk through.  Download the code to be sure to play around with it and learn.  Here are some other helpful resources for you:

Hopefully this will get you started writing Silverlight applications!

| Comments

This past weekend during a conversation about Silverlight controls at the San Diego Silverlight Education Day, someone asked about the DatePicker control and why the “15” is there and how come they can’t change it.  Here’s the control that was being referred to:

Silverlight DatePicker default

The calendar displays an icon to the right of the text box area which, when clicked, displays a drop-down calendar picker.  The icon always says “15” and is intended to look like a little calendar date sheet (you know, like those desk calendars).

The question was how to change that icon.  Well, easily.  You can easily edit the template using Blend and drill into the UI parts and change it.  I opened Blend, chose to edit the template, then edit the Button template and you’ll see that the “15” is actually a Path:

DatePicker custom template in Blend

Now that I know where that template is, I can put anything i want there to replace the Path data to anything I want.  But the question was raised as to why it doesn’t show the current date text instead.  So on the plane ride back I did a quick refactor to see how easy that could be done.

After getting the Ms-PL licensed source code for the DatePicker control from the Silverlight Toolkit, I had access to the full source of the control to get the inner guts.  Here’s what I did. 

First, I changed generic.xaml (located in Themes folder) definition of DatePicker style/template.  I changed the Path to a ContentPresenter (about line 437 in the generic.xaml file).  I removed the Path and replaced it with this:

   1: <ContentPresenter x:Name="DropDownDateText" HorizontalAlignment="Center" Margin="0,0,0,0" 
   2:     VerticalAlignment="Center" RenderTransformOrigin="0.5,0.5" Grid.Column="0" Grid.Row="1" 
   3:     Grid.ColumnSpan="4" Grid.RowSpan="3"/>

Once I had that in place I just went into OnApplyTemplate in DatePicker.cs and after the call to base.OnApplyTemplate() (line 851) I added some additional code:

   1: // change the date to the current date
   2: string DateDay = DateTime.Now.Day.ToString(CultureInfo.CurrentUICulture);
   3:  
   4: // get the Button template and insert the content as current date text
   5: Button b = this.GetTemplateChild(DatePicker.ElementButton) as Button;
   6: TextBlock tb = new TextBlock();
   7: tb.FontFamily = new FontFamily("Arial Bold");
   8: tb.FontSize = 9.5;
   9: tb.FontStretch = FontStretches.Expanded;
  10: tb.UseLayoutRounding = true;
  11: tb.Text = DateDay;
  12: b.Content = tb;

What this does is basically use the local time information to get the current Day text and put that TextBlock as the Content for the button…the result is that the DatePicker now will display the number for the current Date (I took this screenshot on 05 OCT 2009):

Custom DatePicker with current date text

So if I wanted this then I could recompile the source and use my custom DatePicker in my application.  The key difference in this modification is that I’m not using a Path, but a TextBlock.

I’m not sure if this is useful, but since the question was posed and I had time to kill, I thought I’d post my findings.  Having access to the source control for all the Silverlight controls is a great way to customize/extend exactly what you need as well as serving as a great learning resource for you in your control development.

Hope this helps!

| Comments

Just a quick shout-out to congratulate the latest Silverlight MVPs to the program.  The Microsoft MVP (Most Valuable Professional) program is a recognition program that is in place to recognize and reward those individuals who have been identified by individuals (peers, Microsoft staff, etc.) as experts in their technology field and global contributors to the technology. 

Microsoft MVP logo

As of today (01 OCT 2009) we welcome some new folks to the Silverlight group:

All of these folks are great participants in the Silverlight ecosystem and I congratulate them for their efforts.  Be sure to check out all the Silverlight MVPs and subscribe to their blogs!  Thanks to all of you for helping make a great developer ecosystem!

| Comments

Last night I decided to mess around with some older laptops.  I had an HP Pavillion ze2000 CTO laptop (not sure why they call it “CTO” – I guess the Altec Lansing speakers included makes it an executive ;-)).

Works on my machine logoI installed Windows 7 (32-bit) from my home Windows Deployment Server with no problem.  This one took longer than the less-than-20-minute installs I’d been experience.  I’m not sure why.  It wasn’t terribly longer, but about 30-40 minutes I think.  I ran Windows Update and it got all the latest drivers.  A quick check in Device Manager showed no device problems.  Sweet.  I began testing things.  Audio playback was the last thing I played around with.  System sounds, MP3, WMV audio, CD audio…all worked.  Then I put in a DVD (Pirates of the Caribbean to be specific).  The machine suddenly sounded like a machine gun shooting back at me.  Video playback was fine, but audio playback couldn’t work.  I spent a few minutes tinkering then headed to the interweb for help.  My search was hp ze2000 dvd audio not working windows 7 (I type that here in hopes to help some others).  I tried other search terms (dvd audio windows 7 ze2000, dvd audio problems windows 7) and yielded others having problems but no working solution.  Some suggested bad drivers and pointed to older drivers (which I tried and wouldn’t install).

Late in the night I sent a note to my trusty colleague on the Windows test team.  We send a few notes back and forth, then he looped another colleague in and asked me to send the DXDiag report.  2 seconds later I got an email with the classic “try this” note and a few steps.  Boom.  It worked.  I share the works on my machine solution here…it was one of those dreaded checkboxes you wouldn’t think to check.

NOTE: This solution may work and may not.  The fact is that the laptop I have isn’t even a Vista certified machine and the Conexant AC’97 audio driver isn’t supported.  The rep I later talked to was surprised audio even worked at all with Windows 7.  It all works now though!  Your mileage may vary.

THIS IS ONLY A WORK AROUND IF YOU THINK YOU HAVE A SAME PROBLEM ON OLDER MACHINE WHICH USES THE ABOVE AUDIO DRIVER – no need to mess with things working already!

First start up the Sound control panel applet and you’ll see the speakers listed there.  Windows Update found the generic Conexant ACLink Audio driver and installed it already – it indicated that was the latest (date stamp of 2005).

Windows 7 Sound control panel applet

Then choose the properties of the speakers and head to the advanced tab.  When there, UNCHECK the box that reads Allow applications to take exclusive control of this device.

Speaker properties advanced tab

Once unchecked, my DVD audio worked.  Other audio still worked as well. 

Random checkbox setting huh?  I would have taken a long time to get to that setting.  Hopefully this helps others who might be braving upgrading older laptops to Windows 7.  And yes, it runs Windows 7 great.