65.9K
CodeProject 正在变化。 阅读更多。
Home

关于 WPF ImageBrush 的抱怨

starIconstarIconstarIconstarIconstarIcon

5.00/5 (9投票s)

2009年6月17日

CPOL

3分钟阅读

viewsIcon

46058

WPF 中的 ImageBrush

我正在使用 WPF 开发一个 3D 应用,想使用 ImageBrush,但遇到了一些问题,所以决定将其拆分成一个小的测试应用。

我的设置如下

37341/image-thumb.png

我只是想通过创建一个 ImageBrush 来测试它,例如改变 ButtonBackground。所以我有以下代码

   1:              //THIS DOESNT WORK UNLESS I UNCOMMENT THE CODE BELOW, 
   2:              //WHICH IS NOT EVEN RELATED
   3:              System.Windows.Media.ImageBrush brush =
   4:                  new System.Windows.Media.ImageBrush();
   5:              BitmapImage img = new BitmapImage(
   6:                  new Uri(@”images/image1.jpg”, UriKind.RelativeOrAbsolute));
   7:              brush.ImageSource = img;
   8:              btnImage.Background = brush;

我原本以为应该可以工作。但当我运行它时,我得到了

37341/image-thumb1.png

所以我尝试在代码中添加一张图片,现在代码变成了

   1:  <Window x:Class=”ImageBrush.Window1″
   2:      xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation”
   3:      xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml”
   4:      Title=”Window1″ Height=”300″ Width=”300″>
   5:      <StackPanel x:Name=”sp1″>
   6:          <Button x:Name=”btnImage” Margin=”10″ Height=”60″/>
   7:      </StackPanel>
   8:  </Window>

以及代码后台

   1:              //THIS DOESNT WORK UNLESS I UNCOMMENT THE CODE BELOW, 
   2:              //WHICH IS NOT EVEN RELATED   
   3:              System.Windows.Media.ImageBrush brush =   
   4:                  new System.Windows.Media.ImageBrush();   
   5:              BitmapImage img = new BitmapImage(   
   6:                  new Uri(@”images/image1.jpg”, UriKind.RelativeOrAbsolute));   
   7:              brush.ImageSource = img;   
   8:              btnImage.Background = brush;     
   9:   
   10:   
  11:              //BUT IF I UNCOMMENT THESE THE ABOVE CODE WORKS JUST FINE  
  12:              Image img2 = new Image();  
  13:              img2.Source = img;  
  14:              sp1.Children.Add(img2);

这对我来说似乎有效。但我不想使用 Image,所以这个方案不可行。我猜测这一定是 Image 可以做但 ImageBrush 不能做的一些技巧。对于 ImageBrush,我设想我需要从程序集资源中读取。所以我搜索了一下,并在 Tamir Khason 的博客 上找到了以下代码

37341/image-thumb2.png

这允许我们做一些类似的事情

37341/image-thumb3.png

或者对于框架元素

37341/image-thumb4.png

所有这些都非常酷。但这仍然让我觉得不太对劲,所以我问我的朋友 Josh Smith 这个问题,他只是建议将图片的 **Build Action** 更改为 “Content”。这解决了问题,壮观的结果如下所示

37341/image-thumb5.png

太棒了,不是吗。但请注意,当我们设置 **Build Action** 为 “Content” 时,你也会失去本地化该图像的能力。(使用 Resource build action 构建的图像通过 ResourceManager 加载,这意味着它们可以用本地化卫星资源程序集中的图像替换。)

从这里开始,本博客将使用一些与 Ian Griffiths 聊天结果相关的信息。

事实上,完全有可能在 ImageBrush 中使用编译到资源中的资源,你只需要一个更具体的 URI,所以我们可以使用如下 URL

37341/image-thumb6.png

其中我们使用完全限定的 pack URI。顺便说一下,我的测试应用程序名为 ImageBrushAsResource – 显然你需要将你的组件名称放在那里。

实际上,我们可以使用相对路径在 XAML 中为 Image 这样做

37341/image-thumb7.png

它使用 ImageSourceConverter 将该文本字符串转换为 ImageSource,并且使用它的过程与你在代码中使用的过程略有不同。XAML 解析器会将 ImageSourceConverter 传递一个上下文对象,该对象提供一个 IUriContext 服务,让它可以发现包含 XAML 文档的基本 URI,并相对于该 URI 解析 URI。所以它对应于

37341/image-thumb8.png

这允许你使用相对 URI,如原始示例所示。它使用你的窗口的基本 URI 将其转换为完整的 URI,这将类似于 “pack://application:,,,/ImageBrush;component/window1.xaml”,因此它最终将你的相对 URI 解析为我的第一个示例使用的完全限定 URI。但这里的优势是你不需要将其硬编码到代码后台中。你只需要询问 WPF 应该使用什么基本 URI。

因此,通过在代码后台中使用这两种方法中的任何一种,你都可以避免使用 Tamir 的代码。

  • 使用 Resource 的 Build Action,并使用完整的 Pack Uri
  • 使用 Resource 的 Build Action,并使用 BaseUriHelper

总而言之,这是一篇相当有趣的文章,我感觉如此。

© . All rights reserved.