Why won't my external image load in my Silverlight Page?
To make this as simple 开发者_运维问答as possible, I created a new default Silverlight 4 Application and added an Images folder to the test web site that is automatically created when the application is generated. I put the same image, let's call it "imageName.png" in the ClientBin folder and the Images folder. Now, everything works fine when I just use the image in ClientBin using XAML like this:
<Grid x:Name="LayoutRoot" Background="White">
<StackPanel>
<Image Source="imageName.png" Width="16" Height="16"/>
<TextBox Text="Hello" />
</StackPanel>
</Grid>
But the image doesn't load when I try to access the image in the Images folder like this:
<Grid x:Name="LayoutRoot" Background="White">
<StackPanel>
<Image Source="../Images/imageName.png" Width="16" Height="16"/>
<TextBox Text="Hello" />
</StackPanel>
</Grid>
I don't get any errors, but the image just isn't there. Can anyone tell me what's going on? Everything I've been able to find seems to suggest that this should work.
The problem here is that the folder containing the Xap and the top content in the Xap itself is considered to be at the root of the path. Hence the path "/" maps to the top content in Xap and the folder where the Xap is sited (usually ClientBin). Any attempt to use a parent path past what is considered the root will result in a Silverlight Network Error.
Any content outside of the folder that the Xap is found in can only be accessed using an absolute Uri.
What need to do then is convert the relative address containing a parent path to an absolute address before passing it to the Image.Source
property. Preferably we would want to avoid hardcoding the base absolute address into the source code.
We can get the current acquire the absolute Url for the Xap using the BaseAddress
property of the WebClient
object. From that we can compose the desired absolute address by combining it with the relative address even one that contains a parent path.
A value converter can make this easier in Xaml:-
public class WebRelativeConverter : IValueConverter
{
public Uri Base { get; set; }
public WebRelativeConverter()
{
Base = new Uri((new WebClient()).BaseAddress, UriKind.Absolute);
}
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
Uri result = null;
if (value is Uri)
{
result = new Uri(Base, (Uri)value);
}
else if (value != null)
{
result = new Uri(Base, value.ToString());
}
return result;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
Now a fixed value in Xaml would look like this:-
<Grid x:Name="LayoutRoot" Background="White">
<Grid.Resources>
<local:WebRelativeConverter x:Key="wrc" />
</Grid.Resources>
<StackPanel>
<Image DataContext="../Images/imageName.png" Source="{Binding Converter={StaticResource wrc}}" Width="16" Height="16"/>
<TextBox Text="Hello" />
</StackPanel>
</Grid>
Now if you actually were binding the source to a Uri or String property of some object you only need to add the converter and it should work.
精彩评论