为了使这个变得尽可能简单,我创建了一个新的默认Silverlight 4应用程序,并将一个Images文件夹添加到测试网站,该文件夹在生成应用程序时自动创建。我把相同的图像,我们称之为ClientBin文件夹和Images文件夹中的“imageName.png”。现在,当我只使用XAML在ClientBin中使用图像时,一切正常:
<Grid x:Name="LayoutRoot" Background="White">
<StackPanel>
<Image Source="imageName.png" Width="16" Height="16"/>
<TextBox Text="Hello" />
</StackPanel>
</Grid>
但是当我尝试访问Images文件夹中的图像时,图像无法加载:
<Grid x:Name="LayoutRoot" Background="White">
<StackPanel>
<Image Source="../Images/imageName.png" Width="16" Height="16"/>
<TextBox Text="Hello" />
</StackPanel>
</Grid>
我没有任何错误,但图像不存在。谁能告诉我发生了什么事?我能找到的所有东西似乎都表明这应该有效。
答案 0 :(得分:2)
这里的问题是包含Xap的文件夹和Xap本身的顶级内容被认为是路径的根。因此,路径“/”映射到Xap中的顶级内容和Xap所在的文件夹(通常是ClientBin)。任何尝试使用父路径超过被视为根的路径都将导致Silverlight网络错误。
只能使用绝对Uri访问找到Xap的文件夹之外的任何内容。
然后需要做的是将包含父路径的相对地址转换为绝对地址,然后再将其传递给Image.Source
属性。我们希望避免将基本绝对地址硬编码到源代码中。
我们可以使用BaseAddress
对象的WebClient
属性获取当前获取Xap的绝对Url。由此我们可以通过将它与相对地址(甚至包含父路径的地址)相结合来组成所需的绝对地址。
值转换器可以在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();
}
}
现在Xaml中的固定值如下所示: -
<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>
现在,如果您实际上将源绑定到某个对象的Uri或String属性,则只需要添加转换器,它应该可以正常工作。