Welcome to Pete Brown's 10rem.net

First time here? If you are a developer or are interested in Microsoft tools and technology, please consider subscribing to the latest posts.

You may also be interested in my blog archives, the articles section, or some of my lab projects such as the C64 emulator written in Silverlight.

(hide this)

Silverlight 2 Beta 1 Path and File Resolution

Pete Brown - 09 March 2008

How paths are resolved in Silverlight 2 can be somewhat confusing. This has come up a lot in the Silverlight.net forums and elsewhere, so I thought I'd take a stab at putting it all down here. For additional information on Silverlight 2 Beta 1 and how packaging and applications work, see my two part Xap/App posts here: Part 1, Part 2

Images with Leading Slash (like <Image Source="/foo.jpg" />)

This type of references, with a leading slash, is root relative to the application root (the Xap). These files should by Content and have CopyToOutputDirectory set so that they are added into the Xap. If you inspect the Xap, you'll find the image in there.

When not found, the resource loading mechanism falls back to the application's site of origin and looks for the image under the same dir as the Xap is located. Note that this is the application's site, not the hosting page's site. That is an important distinction if you are creating cross-domain applications (where Site X has the page and Site Y has the Xap). If not found, an exception is thrown.

Images without Leading Slash (like <Image Source="foo.jpg" /> )

This type of reference, without any leading slash or anything, expect to find the image compiled into the assembly as a Resource. The path is relative to the path of the Xaml file from which they are being referenced. When not found, the ImageFailed event is raised

If you inspect the Xap, you will not see the image, because it will be in the assembly.

Absolute URLs (like <Image Source="absolute http url" />)

This will look a the named absolute Url as you would expect.

Here's a quick example that shows it:

<UserControl x:Class="PeteBrown.SilverlightPathTest.Page"
    xmlns="http://schemas.microsoft.com/client/2007" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Width="400" Height="300">
    <Grid x:Name="LayoutRoot" Background="Black">
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        
        <!-- Image that is just content, with CopyToOutputDirectory -->
        <Image Source="/Subfolder/image_content.jpg" Grid.Row="0" Grid.Column="0" />
        <TextBlock Text="Content" Foreground="White" Grid.Row="0" Grid.Column="0" />

        <!-- Image that is set as a resource, notice leading slash -->
        <Image Source="Subfolder/image_resource.jpg" Grid.Row="0" Grid.Column="1" />
        <TextBlock Text="Resource" Foreground="White" Grid.Row="0" Grid.Column="1" />

        <!-- Absolute Url -->
        <Image Source="http://www.irritatedvowel.com/pub/blog/SilverlightBalloonsforSilverlight2Beta1_B387/image.png" 
               Grid.Row="0" Grid.Column="2" />
        <TextBlock Text="Absolute" Foreground="White" Grid.Row="0" Grid.Column="2" />

    </Grid>
</UserControl>

Here are the settings in the project for the two files:

image

image

And here is the output:

image

If you look inside the generated Xap file, you'll see the following structure:

  • PeteBrown.SilverlightPathTest.xap
    • AppManifest.xaml
    • PeteBrown.SilverlightPathTest.dll
    • System.Windows.Controls.dll
    • System.Windows.Controls.Extended.dll
    • SubFolder
      • image_content.jpg

Recall that the image_resource.jpg file is compiled as a resource right into the PeteBrown.SilverlightPathTest.dll

Thanks to Ashish Shetty, PM from the Silverlight team, for helping to clear this up for me a while back.

     
posted by Pete Brown on Sunday, March 9, 2008
filed under:      

22 comments for “Silverlight 2 Beta 1 Path and File Resolution”

  1. James Hancocksays:
    So how would one make a URL relative to a site?

    I.e. we want to be able to have our clients brand our silverlight stuff, so we want them to be able to change graphics that are loaded. Thus we want to be able to do what we do in HTML: /Images/SomeImage.png where that relates to the currently hosted site's url.

    With the above example that's not possible. So how would you make it relative without having to hard code the http:// stuff?
  2. Pete Brownsays:
    There is no way to do this in Silverlight 2 Beta 1; you have to use an absolute URL. Now, you can go ahead and pass the site's base URL into the object (as a parameter) when you create the object, but you'll need to code all your image loads instead of relying on the xaml to load them for you.

    The other option is not to host the xap yourself, but to let your customer host it on their site.

    I sent your feedback to the product team. Others have asked for the same thing. One can only hope that they find a way to provide this functionality.

    Pete
  3. James Hancocksays:
    Thanks!

    My suggestion is to use ~/Images/ etc. if you want to make it relative to the site instead of relative to the XAP file... That would solve the entire problem and use a notation that ASP.NET programmers are used to.
  4. Mohamed Mosalemsays:
    Thanks Pete for this post, i have an issue that i can't solve, i have an html page that contains som Windows Image Acquisition (WIA) scripts that gets an image from the scanner and saves it locally on the client machine, what i did was adding a silverlight control to that page that will allow me to manipulatin the image then later uploading it to the server, the problem i have is that there's no way to make the SilverLight display the local image, i tried <Image Source="file://C:/image.png" /> but it doesn't work, i was thinking of saving the image inside the isolated storage folder of my silverlight application but then will i be allowed to access it from the silverlight image control??
  5. Pete Brownsays:
    Hi Mohamed

    For security reasons, the only way you can open a file like this on the client in Silverlight is by using an OpenFileDialog and then setting the image's source to the resulting stream.

    Another option would be for your WIA script to post to the server and download it that way.

    However, since you are using Windows-only functionality, I'd recommend looking at using WPF for this, as it has many more features you'll be able to leverage. Silverlight really shines when it comes to cross-browser, cross-platform capabilities.

    Pete
  6. Troy Hallsays:
    Thanks for the code. It helped solve part of an issue I was having. However, I have another related issue.

    My SL 2 application dynamically loads a bitmap (PNG or JPEG) into a Canvas that a user has uploaded through a web page. (NB: the bitmap is served via the web server, and is not a resource, and not in the .xap file.)

    I have tried a couple of methods for loading the image, including using a WebClient (aka Downloader) to retrieve the bitmap stream, and also setting the source using a BitmapImage initialized with the URI of the bitmap. Both methods load the Image. That's not the problem.

    The problem is, I need to know the dimensions of the image just loaded, as there are some things the app must do right after the image loads. Unfortunately, the Width and Height are always set to Auto (i.e. Double.NaN) right after I set the Image.Source, and are still the same value, even if I try to retrieve them in a BitmapImage.DownloadProgress handler, or in the WebClient.OpenReadCompleted handler. (Actually, in rare cases, the values are correct, indicating some sort of race condition.)

    In addition, the ActualWidth/Height properties are set to -0- in all cases as well.

    I have also tried various other hacks to try to force some sort of layout, including toggling the Image.Visibility property.

    Is there any technique for reliably retrieving the actual width and height of a bitmap loaded either with the WebClient or BitmapImage classes?

    I am getting desperate.

    (And, yes, I'd post this in the Silverlight.net forums, but for some reason, it's hosed for me.)
  7. Ryan Haneysays:
    What I have found is this:

    If I load /test.xaml on the fly into a content control, and it has an image control that loads /me.jpg, all is great. But if /test.xaml has a reference to a custom control, that refers to an image, the "relativity" of that image changes (I am guessing to XAP resolution).

    Interesting!
  8. Billsays:
    Your comments about the use of paths to image resources seems to apply to the main Silverlight control (PeteBrownSilverlightPathTest). But what about images in controls referenced from external assemblies (which in your case might be PeteBrownSilverlightPathTestExternal)?

    I'm finding that the images referenced in such controls will only be displayed if they are added as resources to the main silverlight project. I must be doing something wrong because it would be onerous to expect a user of my control assembly to have to add all my images to their silverlight project.

    How can I include a resource in a control assembly (not the main assembly) and have it be used from Xaml within that control assembly?
  9. Billsays:
    I'm posting my own answer to try to ensure no one wastes their time responding. The answer is to use the pack uri syntax correctly. I'd used

    mycontrolassemblyname;img/myimage.jpg

    when in Silverlight it should be:

    mycontrolassemblyname;/component/img/myimage.jpg

    Sublte but important difference. Still the image doesn't show up at design-time but at least its there at run-time.
  10. Sarahsays:
    I recently came across your blog and have been reading along. I thought I would leave my first comment. I don't know what to say except that I have enjoyed reading. Nice blog. I will keep visiting this blog very often. Sarah
  11. Davesays:
    How silly.

    It's one thing to call a URI starting with a slash a "relative" URI.

    It's another to make it relative from the xap and not the loading page.

    It's yet another to not also allow "../" to move *up* from the ClientBin directory. :grumble grumble: Silverlight...
  12. Pete Brownsays:
    @Dave

    I believe they did all of those things for security reasons.

    If this is a blocker, you can put the xap anywhere, so just plop it in the same location as the page that loaded it, or put it at the root of the site.

    Pete
  13. Jamessays:
    To add a little to Bill's comment - if you want to create a dll of custom components, and you want an image in the default template of one of them, i.e. you want to refer to an image in generic.xaml, the best way to do this is put the image into the dll project as a resource and refer to it with pack syntax e.g. Source="/MyApp.Controls;component/myimage.png". You have to use pack syntax even though the image is in the same project as generic.xaml if you are going to refer to all this from outside the project you've built.
  14. Andrussays:
    I tried (in MSDN SilverlightTextEditor sample)

    copyImage.Source = new BitmapImage(new Uri("/Images/Copy.png", UriKind.RelativeOrAbsolute));

    Image is in /Images/Copy.png
    Build action: Resource

    but image is not displayed, no warning appears in debug output window. How to show this image ?

Comment on this Post

Remember me

9 trackbacks for “Silverlight 2 Beta 1 Path and File Resolution”

  1. Christopher Steensays:
    ASP.NET LinkButtons in UpdatePanel cause full postback unless you give them IDs [Via: alexcampbell ]...
  2. Community Blogssays:
    Bill Reiss posted his SL2 Game Loop part 1, Pete Brown on XAP, SL2 startup, and the Uri Issue, Daniel
  3. Mike Taulty's Blogsays:
    Path and File resolution in Silverlight 2 is confusing so, fortunately, Pete Brown has a good post on...
  4. Method ~ of ~ failedsays:
    Skinning an embeddable Silverlight 2 media player
  5. Tim Heuersays:
    While Silverlight 2 brings us great capabilities as .NET developers and opens many opportunities for
  6. Blogssays:
    While Silverlight 2 brings us great capabilities as .NET developers and opens many opportunities for
  7. Blogssays:
    While Silverlight 2 brings us great capabilities as .NET developers and opens many opportunities for
  8. Tim Heuersays:
    While Silverlight 2 brings us great capabilities as .NET developers and opens many opportunities for