Rants Tagged with “Silverlight 2”

<<  <  1  2  3  4  5  6  7  8  9  10  11  +  >  >>  (Total Pages: 13/Total Results: 127)

Understanding Image and Media Failed Errors

Silverlight Logo

In meeting with a client (Schoolmaster.nl who is building a cool LOB app), we came across the problem of one of their components was throwing Image Failed Javascript errors. Handling them in the App.UnhandledException event didn't help because the errors were surfaced outside the plug-in, directly to Javascript.  Immediately I use the VisualTreeHelper to walk the entire XAML tree (including nested templates) to just add an event handler on to every ImageFailed events to try and suppress these errors. 

public Page()
{
  InitializeComponent();

  Loaded += (s, e) =>
    {
      // Call Recursive method to wire all Image tags
      WireImageFailed(this);
    };
}

void WireImageFailed(DependencyObject source)
{

  for (int x = 0; x < VisualTreeHelper.GetChildrenCount(source); ++x)
  {
    DependencyObject child = VisualTreeHelper.GetChild(source, x);
    if (child is Image)
    {
      ((Image)child).ImageFailed += (s,e)=>
        {
          // NOOP
        };
    }
    WireImageFailed(child);
  }

}

In case you're not familiar with this class, it helps you walk through the entire render tree at runtime (including inside controls and control templates). This means I could look for all the Image objects and handle the event to suppress the error. This worked but it felt hacky and doesn't work for them as they are building a lot of dynamic XAML.

After digging further, I found out that for compatibility with Silverlight 1.0, they are actually thrown at the Plug-in level so if you want to suppress them, just handle the OnError on the plugin. You can do this no matter how you are hosting the plugin:

<!-- ASP.NET Silverlight Control -->
<asp:Silverlight ID="Xaml1" 
                 runat="server" 
                 Source="~/ClientBin/BadImageTest.xap"
                 MinimumVersion="2.0.31005.0" 
                 Width="100%" 
                 Height="100%" 
                 OnPluginError="SLPluginError" />

<!-- OBJECT Tag -->
<object data="data:application/x-silverlight-2," 
        type="application/x-silverlight-2" 
        width="100%" 
        height="100%">
	<param name="source" 
	       value="ClientBin/BadImageTest.xap"/>
	<param name="minRuntimeVersion" 
	       value="2.0.31005.0" />
	<param name="onerror" 
	       value="SLPluginError" />
</object>

By handling the plugin error, we can either do something about it or just ignore the image/media errors:

function SLPluginError(sender, args) {
  // NOOP
}

Its not elegant, but if you want to stop those annoying script errors from the plug-in, this is the way. At least until I get Microsoft to agree that this isn't a valid way to handle it.

 

Updating My Sites to Silverlight 2 RTW

Silverlight Logo

I've started updating my sites that use Silverlight 2 to the RTW bits. So far I've got silverlight-tour.com and wildermuth.com updated.  SilverlightData.com will have to wait a few days as I have a completely new example that is more complete and dynamically switches between NHibernate and Entity Framework.  Look for an announcement on that this weekend.

The only caveat I have for updating your site is if you're using the Silverlight ASP.NET Control to host your projects. You can copy the SDK to your server if you want but I found that the upgrade to RTW works seemlessly except that I changed the reference to "CopyLocal=True" so I can copy the control to my server instead of expecting it to be installed on the server.

Silverlight 2 Released!

Silverlight Logo

Its been a long road to release but we're finally there. If you're anything like me and have been through WPF/E, Silverlight 1.0, Silverlight 1.1, Silverlight 2 Beta 1, Beta 2 and RC0, I know you're ready for this thing to hit the streets.

I would like to congratulate the team on a solid set of functionality and tooling. For a fairly new product, this technology has progressed much faster than I expected it to. When asked some months ago, I didn't think Silverlight would be in this great a shape until Silverlight 3.  The control model, data binding, data access, tool support, visual state manager, etc. Its all a much bigger leap from Silverlight 1.0 that I could have possibly envisioned.

There are a number of changes since Beta 2 (though this list is the same as the RC) that I want to make sure you know about:

  • Visual Studio 2008 now requires SP1 to be applied before the Silverlight 2 tools will work so make sure you have updated to the Service Pack 1 before you try to install the tool package.
  • Blend 2.5 is now a Service Pack for Blend 2.  You'll need Blend 2 then you can apply Service Pack 1.
  • Rendering is now pixel-aligned by default. In earlier versions you could do sub-pixel rendering which could result in odd or aliased designs.  In the release, all rendering is pixel-aligned unless you override it with FrameworkElement.UseLayoutRounding which is true by default.  Setting it to default will do sub-pixel rendering.
  • For hosting Silverlight with an <OBJECT /> Tag, you must change your type from "application/x-silverlight-2-b2" to "application/x-silverlight-2".
  • For embedded fonts, font URI's must be resource based (instead of XAP based). That means that relative URI's for font's must point to a font-file as a resource inside an assembly instead of as a file inside the .xap file.  If you are using Blend 2 to embed your fonts, this will happen by default.  If you are refactoring old code, changing the font's "Build Action" from "Content" to "Resource" should do the trick.
  • If you are using the VisualStateManager, you will need to change VisualTransition.Duration to VisualTransition.GeneratedDuration.  This usually means changing the "Duration" attribute in your ControlTemplates to "GeneratedDuration". 
  • If you are using the KeyDown event, you'll be happy to find out that the event is now delivered asynchronously.  In Beta 2 and before you could get into re-entrancy issues.  You may need to tweak your use of this event to deal with this new model.
  • OpenFileDialog no longer uses the FileDialogFileInfo class but instead changes the API to simply the use of the selected files.  If you use the dialog, you'll need to adjust the use.
  • Most controls now have a new default control template that should be less Window'y.  If you have made some minor changes to those templates for your own, you will find that they don't match any longer. Because of this you might want to re-skin them in Blend.
  • Finally, the biggest painful change for you is to make sure that your styles and control templates are in the right order. In previous revisions, the rules were lax around StaticResources having to be defined before they are used. This caused a lot of problems for tooling and inconsistent runtime behavior.  To address this you *must* have a related resource defined before its used.  This may mean re-ordering your control templates.

I hope this opens up the more conservative uses of Silverlight 2 and allows Silverlight to move from an 'early-adopter' technology to a mainstream way to build Internet-based applications.

Also announced was the fact that you can use Eclipse now to write Silverlight 2 applications.  Cool!  http://www.eclipse4sl.org/  It'll be licensed under the EPL 1.0 License.

Also announced was the new Controls from Shawn Burk's team to be released on CodePlex!  These controls include:

  • DockPanel
  • WrapPanel
  • ViewBox
  • Label
  • HeaderedContentControl
  • Expander
  •  TreeView
  • NumericUpDown
  • AutoComplete
  • Accordion

These controls and their test-suite will be covered under MS-PL so they will be ready (including source code) coming pretty soon. 

What do you think?

Dirty Little Secrets - Episode 2

Silverlight Logo

My second episode of my "Dirty Little Secrets" screencast is up. This time I show you how to use control templates to skin a complex control in Silverlight 2. I create a ListBox with a Data Template and use ControlTemplates to skin the entire ListBox, Scrollbars, ListBoxItem and all.  Check it out!

You can view the episode online here:

http://wildermuth.com/dls/Dirty_Little_Secrets_Episode_2

Or subscribe to the RSS feed:

Subscribe with RSS
Subscribe with iTunes

Add Shawn Wildermuth&#039;s Dirty Little Secrets Screencast to ODEO 

ADO.NET Data Services and TimeZone

Silverlight Logo

There is a known problem with ADO.NET Data Services today that is important if you (or your server) lives in specific timezones.  The problem is associated with the way that the Silverlight Data Services Library constructs their URI for searches. 

The problem surfaces if you do a query that has a DateTime comparison in it. For example:

var qry = from o in ctx.Orders
          where o.OrderDate <= dt
          select o;

This query generates the following URI in the EST timezone in the US:

http://.../ProductService.svc/Orders()?$filter=OrderDate le datetime'2008-10-13T00:00:00-04:00'

This works great. The problem is that in other timezones (e.g. Bulgaria) where its forward of Greenwich Mean Time, so the UTC date is +03:00 like so:

http://.../ProductService.svc/Orders()?$filter=OrderDate le datetime'2008-10-13T00:00:00+03:00'

Because the "+" isn't URL Encoded, it becomes a space which makes the date incorrect.  For now you can convert the date to universal time but that's a hack at best:

var qry = from o in ctx.Orders
          where o.OrderDate <= DateTime.Today.ToUniversalTime()
          select o;

It works but its a hack.

Silverlight Tour Goes RC

Silverlight Logo

Don't miss your chance to take the first Silverlight Tour stop that is supporting the impending release of Silverlight 2.  Starting with the Atlanta, Georgia - October 22-24th stop of the Silverlight Tour, the course will be taught using Silverlight 2 RC (or the full release once that happens).

The Silverlight Tour is a three-day intensive Silverlight 2 workshop that teaches the basics of designing Silverlight 2 applications including design, development, services, control development, control skinning and security.

New Information on WebClient in Silverlight 2

Silverlight Logo

After digging and some prodding by a PM at Microsoft, I realize that the relative URI story in WebClient is different that I expected.  I am not sure whether this changed from previous versions but Beta 2 and the RC this is the way that Relative URI's work in WebClient:

  • WebClient supports a BaseAddress property (read/write) that by default contains the path to the .xap file (though you could replace it with HtmlPage.Document.DocumentUri.ToString() to resolve to the current page).
  • It uses the BaseAddress to calculate the relative URI
  • This is not the same as the Image/Media "Site of Origin" relative URI problem (see my post about that here).
  • In most cases a relative URI in WebClient will do the right thing and supporting the BaseAddress will allow you to change the basis for the relative URI's pretty easily.

Note that the WebRequest classes (BrowserHttpRequest specifically) does not support relative URI's so if you want to use that class instead of WebClient, you'll have to do your own relative URI resolution. 

The Silverlight Tour in the UK

Saffron Interactive

I am happy to announce our newest partner for the Silverlight Tour: Saffron Interactive. They will be teaching the Silverlight Tour materials in the United Kingdom including their first class on December 3-5, 2008 in London, England.

For this first class I will be teaching the class so if you are in London and have been hoping to take the class from me, this is your one opportunity as Saffron will be teaching all subsequent classes. 

WebClient vs. WebRequest in Silverlight 2

Silverlight Logo

When making web requests in Silverlight 2, its easy to start with the simple WebClient class. In fact, it supports making simple requests (DownloadStringAsync and OpenReadAsync) as well as uploading through the class. On the other hand there are some that swear by the WebRequest route. What's the big difference?

Let's start with WebRequest. The pattern for WebRequest is to call WebRequest.Create:

Uri url = new Uri("http://localhost:8889/Silverlight.js", UriKind.Absolute);
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);;

Notice that we are actually using a HttpWebRequest object and casting the return value of the Create call. In reality this object is a BrowserHttpWebRequest object. This class represents a web request in Silverlight 2 (since all requests are actually routed through the browser's networking stack). The reason for this is to make sure that any requests are part of the page.  This means that when you make a request in Silverlight 2 it is bringing with it the same Session ID and cookies.  This also means that for large sized requests, the user may cancel the request.

To execute the request, we need to get a WebResponse object that contains our results of the request. To do this, ordinarily you would call the HttpWebRequest's BeginGetResponse method:

req.BeginGetResponse(new AsyncCallback(WebComplete), req);

This method specifies that you create an AsyncCallback object that describes the callback once the request is complete.  The WebComplete object in the AsyncCallback is actually the method to call (though you could use a delegate or lambda here):

void WebComplete(IAsyncResult a)
{
  HttpWebRequest req = (HttpWebRequest)a.AsyncState;
  HttpWebResponse res = (HttpWebResponse)req.EndGetResponse(a);
  Dispatcher.BeginInvoke(() => status.Text = "Downloading...Done.");
}

Note that we're retrieving the request from the AsyncState and then calling EndGetResponse to complete the operation. The most important thing to understand inside this callback is that it does not happen on the UI thread so any calls to update the UI will result in InvalidThreadAccessExceptions. Typically this means using the Dispatcher to call the UI thread as necessary (as shown). In addition, the response contains a stream that contains the results of the request. To retrieve the data, you need to write code to dig it out of the stream as necessary...not hard, but another step.

In contrast, the WebClient class performs this operation very differently. First, it supports two different request styles: DownloadString and OpenReadDownloadString support the ability to retrieve a string with the contents of the request. The OpenRead style returns a Stream instead. This way you can decide if you need a simple way to retrieve just a string, otherwise you can use the tried and true way of consuming a Stream.

Another change is the WebClient class uses events not AsyncCallbacks to complete the asynchronous model.  The events and execution start of each of the styles are paired up with Completed events and Async execution methods. For example, to make a request with the WebClient with the DownloadString style: 

WebClient client = new WebClient();
client.DownloadStringCompleted += 
  new DownloadStringCompletedEventHandler(client_DownloadStringCompleted);
client.DownloadStringAsync(new Uri("/Silverlight.js", UriKind.Relative));

The other big difference is that the WebClient class handles the context switch for the user. What this means is that when the event is fired, it is always called on the UI thread. So your event handling code can update the UI directly as so:

void client_DownloadStringCompleted(object sender, 
                                    DownloadStringCompletedEventArgs e)
{
  status.Text = "Downloading...Done.";
}

So what's the verdict?  There is none. They both are fine to use.  In fact, under the covers the WebClient class uses the BrowserHttpWebRequest class so that it does not matter. If you find the WebClient class easier to use, go ahead. But if you are already familiar with the HttpWebRequest-style classes and AsyncCallback objects, continue to do what you're comfortable with. Just understand the differences between these workhorses of Silverlight 2.

What do you use?

Silverlight 2 Tools Release Candidate Now Available

Silverlight Logo

In case you haven't heard yet, Microsoft announced that a Release Candidate of the Silverlight 2 tools are now available. You can download it now here:

Included is the Silverlight 2 SDK, Silverlight 2 Visual Studio Tools, the Silverlight 2 Developer Runtime and Blend 2 SP1 (was called Blend 2.5 but is now a patch to Blend 2 instead). Note that the Release Candidate should give you time to get your applications ready for release, but that the runtime won't be generally available on the Internet until Silverlight 2 reaches release. Unlike when Silverlight 2 Beta 2 was released, you won't have to rush to fix your applications.

This means there is no "Go-Live" license with the Release Candidate, but you can modify your code to be compatible with the release and be ready to deploy them once the RTW (Release to Web) happens (which hopefully will happen soon).

Note: Beta 2 users will automatically be upgraded to the RTW version once its available.

Also make sure you look at the Breaking Changes document to see what's changed.  The changes are not dramatic but there are a couple of surprises:

  • By default all rendering is now pixel aligned.  This should allow you to avoid that sub-pixel rendering issues that plagued earlier releases.  You can enable sub-pixel rendering if you need it.
  • Blend 2 SP1 now supports the Font Manager (so you can embed and even subset fonts automatically).
  • New controls were released (ComboBox, ProgressBar and PasswordBox).
  • Fonts now must be assembly resources (no more free floating fonts in the .xap file).
  • Custom Control XAML files now must exist in a themes folder instead of at the root of the project.

For all the changes, please review the Breaking Changes document.

I am currently converting all my examples to RTW and they will ship when the release happens.