相对URI在BitmapImage中不起作用

时间:2016-11-28 07:57:13

标签: c# xaml

我有一种加载图像的方法,以供以后通过绑定使用。

当我按如下方式设置时,它可以工作:

public static ImageSource LoadImage()
{
    return new BitmapImage(
        new Uri("C:/User/Name/Documents/Visual Studio 2015/Projects/Project/bin/debug/subfolder/sprite.png", UriKind.Absolute));
}

然而,当我换成简单地使用:

public static ImageSource LoadImage()
{
    return new BitmapImage(
        new Uri("/subfolder/sprite.png", UriKind.Relative));
}

XAML没有显示图像。我查看了Environment.CurrentDirectory,然后返回"C:/User/Name/Documents/Visual Studio 2015/Projects/Project/bin/debug/"

我已经用Google搜索解决方案,但似乎无法看到任何内容。

6 个答案:

答案 0 :(得分:0)

如果您希望图像位于输出文件夹中。将您的图像添加到项目中,在Build Action中选择“Content”,然后在Copy to output directory选项中选择“Copy Always”。

您将在输出中获取图像,然后您可以使用Relative URI命令加载它。

答案 1 :(得分:0)

您应该从程序集资源文件中加载图像。

确保映像文件位于名为subfolder的Visual Studio项目文件夹中,并将其Build Action设置为Resource。然后按Resource File Pack URI

加载它
public static ImageSource LoadImage()
{
    return new BitmapImage(new Uri("pack://application:,,,/subfolder/sprite.png"));
}

答案 2 :(得分:0)

如果您不在项目中的任何地方使用它,并且将其标记为“资源”,则该图像将不包含在最终版本中。点击图片,然后在“生成操作”字段中选择“内容”。

答案 3 :(得分:0)

虽然我看到了你的评论,但我可以肯定地告诉你,你需要删除前导斜杠。

这个语法没有问题:

return new BitmapImage(new Uri("subfolder/sprite.png", UriKind.Relative));

我不会完全信任 Environment.CurrentDirectory,因为我不知道 BitmapImage 如何处理相对 uri。

您可以尝试手动运行可执行文件,确保“子文件夹”在同一文件夹中。

当然,另一种选择是获取完整路径:

var fullPath = Path.GetFullPath("subfolder/sprite.png");
return new BitmapImage(new Uri(fullPath, UriKind.Absolute));

答案 4 :(得分:0)

查看具有不同路径定义的示例:

    public class ImageUriViewModel
    {
        public Uri AbsoluteUri { get; }
        public Uri RelativeUri { get; }
        public Uri AbsoluteFromRelativeUri { get; }
        public Uri AssemblyRelativeUri { get; }
        public ImageSource AbsoluteImage { get; }
        public ImageSource RelativeImage { get; }
        public ImageSource AbsoluteFromRelativeImage { get; }
        public ImageSource AssemblyRelativeImage { get; }

        public ImageUriViewModel()
        {
            // Full path on my computer.
            string AbsolutePath = "C:/Users/EldHa/Мои проекты/CyberForurm/CyberForurmWpf/Febr20y/bin/Debug/Images/sprite.png";

            // Relative path on my computer.
            // Note: there is no leading slash!
            // The leading slash is interpreted as the path from the Root folder on the current drive.
            string RelativePath = "Images/sprite.png";


            AbsoluteUri = new Uri(AbsolutePath, UriKind.Absolute);
            RelativeUri = new Uri(RelativePath, UriKind.Relative);
            AbsoluteFromRelativeUri = new Uri(System.IO.Path.GetFullPath(RelativePath));
            AssemblyRelativeUri = new Uri(System.IO.Path.GetFullPath(System.IO.Path.Combine(System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), RelativePath)));

            AbsoluteImage = GetImage(AbsoluteUri);
            RelativeImage = GetImage(RelativeUri);
            AbsoluteFromRelativeImage = GetImage(AbsoluteFromRelativeUri);
            AssemblyRelativeImage = GetImage(AssemblyRelativeUri);
        }

        private static ImageSource GetImage(Uri uri)
        {
            try
            {
                return new BitmapImage(uri);
            }
            catch (Exception)
            {
                return NotFile;
            }
        }

        private static readonly ImageSource NotFile;

        private static readonly double pixelsPerDip = VisualTreeHelper.GetDpi(new UIElement()).PixelsPerDip;

        static ImageUriViewModel()
        {
            FormattedText text = new FormattedText("Not\r\nFile",
                                    CultureInfo.CurrentCulture,
                                    FlowDirection.LeftToRight,
                                    new Typeface("Tahoma"),
                                    12,
                                    Brushes.Black,
                                    pixelsPerDip);
            Geometry textGeometry = text.BuildGeometry(new Point());

            GeometryDrawing drawing = new GeometryDrawing(null, new Pen(Brushes.Red, 1), textGeometry);
            NotFile = new DrawingImage(drawing);
            NotFile.Freeze();
        }
    }
    <Window.DataContext>
        <local:ImageUriViewModel/>
    </Window.DataContext>
    <UniformGrid Background="AliceBlue" Columns="1">
        <TextBlock Text="{Binding AbsoluteUri}" />
        <Image Source="{Binding AbsoluteImage}"/>
        <TextBlock Text="{Binding RelativeUri}" />
        <Image Source="{Binding RelativeImage}"/>
        <TextBlock Text="{Binding AbsoluteFromRelativeUri}" />
        <Image Source="{Binding AbsoluteFromRelativeImage}"/>
        <TextBlock Text="{Binding AssemblyRelativeUri}" />
        <Image Source="{Binding AssemblyRelativeImage}" />
    </UniformGrid>
</Window>
  1. 在 XAML 设计器工作室中:
  • AbsoluteUri 和 RelativeUri 工作正常;
  • AbsoluteFromRelativeUri 的值是相对于 Windows/System32 文件夹的;
  • AssemblyRelativeUri 值是相对于带有 cash Studio 的文件夹。
  1. 当从带有 exe 文件的文件夹(包括在 Studio 中运行)启动执行时 - 一切正常。

  2. 当从另一个文件夹(例如桌面上的快捷方式)启动执行时:

  • AbsoluteUri、RelativeUri 和 AssemblyRelativeUri 工作正常;
  • AbsoluteFromRelativeUri 定义相对于当前文件夹的路径。

答案 5 :(得分:0)

您必须保留相对 URI 的前导 File.AppendAllLinesAsync,这会使路径成为根目录,从而忽略任何基本 URI 的完整目录结构:

/

Live example


更新:

至于 var baseUri = new Uri("C:/User/Name/Documents/Visual Studio 2015/Projects/Project/bin/debug/"); var relative1 = new Uri("/subfolder/sprite.png", UriKind.Relative); var relative2 = new Uri("subfolder/sprite.png", UriKind.Relative); // file:///C:/subfolder/sprite.png Console.WriteLine(new Uri(baseUri, relative1)); // file:///C:/User/Name/Documents/Visual Studio 2015/Projects/Project/bin/debug/subfolder/sprite.png Console.WriteLine(new Uri(baseUri, relative2)); 本身:像往常一样,官方 WPF 帮助确实有一些改进的空间。

  • BaseUri 中没有提到它的默认值实际上是 BitmapImage 而不是当前工作目录。
  • 虽然在 UriSource 中有一些示例(混合路径是否有根),但他们忘记提及这仅在源是嵌入式资源时才有效。他们真的可以放置一个指向 this page 的链接。

如果您不想将图片打包为资源,那么您有两个选择:

解决方案 1:改用 StreamSource 属性

当然,StreamSource 属性的文档也很稀缺,只提到加载图片后,要将pack://application:,,,/ProjectName;component/WindowName.xaml 设置为CacheOption 才能关闭流。但简单地设置 OnLoad 是行不通的,所以完整的解决方案:

StreamSource

方案二:设置BaseUri

如果您不介意覆盖 public static ImageSource LoadImage(string relativePath) { var bmp = new BitmapImage(); bmp.BeginInit(); bmp.CacheOption = BitmapCacheOption.OnLoad; bmp.StreamSource = File.OpenRead(relativePath); bmp.EndInit(); return bmp; } 中的默认 pack://... 值,正确的解决方案如下:

BaseUri