【问题标题】:Storing WPF Image Resources存储 WPF 图像资源
【发布时间】:2010-09-25 17:53:59
【问题描述】:

对于需要 10 到 20 个小图标和图像用于说明目的的 WPF 应用程序,将这些作为嵌入式资源存储在程序集中是正确的方法吗?

如果是这样,我如何在 XAML 中指定 Image 控件应从嵌入式资源加载图像?

【问题讨论】:

    标签: c# .net wpf embedded-resource


    【解决方案1】:

    是的,这是正确的方法。您可以使用路径在资源文件中使用图像:

    <StackPanel Orientation="Horizontal">
        <CheckBox  Content="{Binding Nname}" IsChecked="{Binding IsChecked}"/>
        <Image Source="E:\SWorking\SharePointSecurityApps\SharePointSecurityApps\SharePointSecurityApps.WPF\Images\sitepermission.png"/>
        <TextBlock Text="{Binding Path=Title}"></TextBlock>
    </StackPanel>
    

    【讨论】:

      【解决方案2】:

      以下工作并且要设置的图像是属性中的资源:

          var bitmapSource = Imaging.CreateBitmapSourceFromHBitmap(MyProject.Properties.Resources.myImage.GetHbitmap(),
                                            IntPtr.Zero,
                                            Int32Rect.Empty,
                                            BitmapSizeOptions.FromEmptyOptions());
          MyButton.Background = new ImageBrush(bitmapSource);
      img_username.Source = bitmapSource;
      

      【讨论】:

      • 无意冒犯,但这闻起来像是不好的做法。
      【解决方案3】:

      在执行程序集中加载资源的代码中,我的图像 Freq.png 位于文件夹 Icons 中并定义为 Resource

      this.Icon = new BitmapImage(new Uri(@"pack://application:,,,/" 
          + Assembly.GetExecutingAssembly().GetName().Name 
          + ";component/" 
          + "Icons/Freq.png", UriKind.Absolute)); 
      

      我也做了一个函数:

      /// <summary>
      /// Load a resource WPF-BitmapImage (png, bmp, ...) from embedded resource defined as 'Resource' not as 'Embedded resource'.
      /// </summary>
      /// <param name="pathInApplication">Path without starting slash</param>
      /// <param name="assembly">Usually 'Assembly.GetExecutingAssembly()'. If not mentionned, I will use the calling assembly</param>
      /// <returns></returns>
      public static BitmapImage LoadBitmapFromResource(string pathInApplication, Assembly assembly = null)
      {
          if (assembly == null)
          {
              assembly = Assembly.GetCallingAssembly();
          }
      
          if (pathInApplication[0] == '/')
          {
              pathInApplication = pathInApplication.Substring(1);
          }
          return new BitmapImage(new Uri(@"pack://application:,,,/" + assembly.GetName().Name + ";component/" + pathInApplication, UriKind.Absolute)); 
      }
      

      用法(假设您将函数放在 ResourceHelper 类中):

      this.Icon = ResourceHelper.LoadBitmapFromResource("Icons/Freq.png");
      

      注意:见MSDN Pack URIs in WPF:
      pack://application:,,,/ReferencedAssembly;component/Subfolder/ResourceFile.xaml

      【讨论】:

      • new Uri throws Invalid URI: Invalid port specified.
      • 你有违规的 uri 吗?
      • 与您的 uri 相同,只是我的 uri 在 winform 托管的 WPF 中运行。当我调用 new Uri 时,“pack”模式还没有注册。
      • 糟糕...这可能与 winform 托管的 WPF 相关。对不起。我不会尝试修复它,因为我认为这不是很常见的用法。祝你好运!
      • 在我的情况下,使用new Uri(@"pack://application:,,,/" + pathInApplication) 也可以解决问题。
      【解决方案4】:

      如何使用资源的完整说明:WPF Application Resource, Content, and Data Files

      以及如何引用它们,请阅读“Pack URIs in WPF”。

      简而言之,甚至可以通过引用/引用程序集引用资源。

      【讨论】:

      • 链接看起来很有效(虽然它说“此文档已存档,未维护。”)。
      【解决方案5】:

      我发现使用图像、视频等的最佳做法是:

      • 将您的文件“构建操作”更改为“内容”。请务必检查复制到构建目录
        • 在“解决方案资源管理器”窗口的“右键单击”菜单中找到。
      • 图片来源,格式如下:
        • "/«YourAssemblyName»;component/«YourPath»/«YourImage.png»"

      示例

      <Image Source="/WPFApplication;component/Images/Start.png" />
      

      好处:

      • 文件未嵌入到程序集中。
        • 资源管理器会在资源过多时引发一些内存溢出问题(在构建时)。
      • 可以在程序集之间调用。

      【讨论】:

      • 如果您将资源嵌入程序集中,同样的方法也适用,但您必须将“构建操作”设置为“资源”。
      • 工作,谢谢。给其他人的注意事项:“组件”是“原样”所必需的,“图像”是项目中 png 的相对路径。 IE。放置在根目录中的图像将是“
      • 一个如何在 C# 中执行此操作的示例会很好。 (这不是一个有效的 URI,因此在构造 BitmapImage 时不能使用它。)
      • 那么,如果文件设置为嵌入式资源怎么办呢?这似乎不起作用。而且我不想在我的项目中包含两次图像。 (我已经将它用作嵌入式资源。)
      • “组件”在何处以及如何进入路径。那是某些规范的一部分吗?
      【解决方案6】:

      如果您使用的是Blend,为了使其更加简单并且在获取 Source 属性的正确路径时不会遇到任何问题,只需将图像从“项目”面板拖放到设计师。

      【讨论】:

        【解决方案7】:

        是的,这是正确的方法。

        您可以使用资源文件中的图像,只需使用路径:

        <Image Source="..\Media\Image.png" />
        

        您必须将图像文件的构建操作设置为“资源”。

        【讨论】:

        • 谢谢。有没有办法用 ImageSource 做类似的事情,本质上是将图像加载到资源字典中。我担心这种方法会在内存中多次加载图像数据。
        • 当您需要重构代码时,这将是一团糟。如果您的 xaml 文档碰巧更改了命名空间,您将不得不手动更改所有图像引用。 Drew Noakes 描述的方法更加流畅且易于维护。
        【解决方案8】:

        如果您将在多个地方使用图像,那么值得将图像数据仅加载一次到内存中,然后在所有Image 元素之间共享。

        为此,请在某处创建一个BitmapSource 作为资源:

        <BitmapImage x:Key="MyImageSource" UriSource="../Media/Image.png" />
        

        然后,在您的代码中,使用类似:

        <Image Source="{StaticResource MyImageSource}" />
        

        就我而言,我发现我必须将Image.png 文件设置为具有Resource 的构建操作,而不仅仅是Content。这会导致图像在您编译的程序集中携带。

        【讨论】:

        • 是否可以动态执行此操作?如果我想在启动时加载不同数量的图像,我可以为每个图像创建一个 BitmapSource 并以与上述相同的方式引用它们吗?
        • @Becky - 是的,你可以,但如果你想在 Xaml 中引用它们,那么你可能需要使用 DynamicResource 标记扩展而不是 StaticResource,假设你知道在编译时间。在 WPF 中,您可以在运行时创建资源字典。事实上,当您加载 Xaml 文档时会发生这种情况,只是您没有看到等效的 C#。
        • 我遇到的问题:如果您将图像资源添加到资源字典中,请不要忘记在 XAML 中为您的组件引用该图像字典。类似于:
        • 我通常将Width="{Binding Source.PixelWidth, RelativeSource={RelativeSource Self}}" 添加到Image,否则我经常会看到由于某种原因(例如 16x16 图标被拉伸到看起来像 200x200 像素的东西),图像被奇怪地放大了。跨度>
        • 我发现如果 BitmapImage 在引用程序集的资源字典中声明,则 UriSource 需要是 packURI 才能工作。否则,你会发现在 VS 的 xaml 编辑器中可以看到图像,但在调试的时候看不到图像。打包URI:msdn.microsoft.com/en-au/library/aa970069(v=vs.100).aspx
        【解决方案9】:
        1. Visual Studio 2010 专业版 SP1。
        2. .NET Framework 4 客户端配置文件。
        3. PNG 图像作为资源添加到项目属性中。
        4. 自动在 Resources 文件夹中创建新文件。
        5. 构建操作集为资源。

        这对我有用:

        <BitmapImage x:Key="MyImageSource" UriSource="Resources/Image.png" />
        

        【讨论】:

          【解决方案10】:

          有些人询问是否在代码中执行此操作,但没有得到答案。

          找了好几个小时找到了一个很简单的方法,没有找到例子,所以在这里分享一下 它适用于图像。 (我的是 .gif)

          总结:

          它返回 ImageSource“目的地”似乎喜欢的 BitmapFrame。

          用途:

          doGetImageSourceFromResource ("[YourAssemblyNameHere]", "[YourResourceNameHere]");
          

          方法:

          static internal ImageSource doGetImageSourceFromResource(string psAssemblyName, string psResourceName)
          {
              Uri oUri = new Uri("pack://application:,,,/" +psAssemblyName +";component/" +psResourceName, UriKind.RelativeOrAbsolute);
              return BitmapFrame.Create(oUri);
          }
          

          学习:

          根据我的经验,包字符串不是问题,请检查您的流,特别是如果第一次阅读它已经设置了指针 到文件末尾,您需要将其重新设置为零才能再次读取。

          我希望这可以为您节省很多时间,我希望这篇文章对我有用!

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2011-01-24
            • 1970-01-01
            • 2011-05-03
            • 2011-03-02
            • 2014-11-01
            • 2019-03-09
            相关资源
            最近更新 更多