我试着写代码,这将负载一个影像从资源,然后作物。这个代码作品当我做的所有或一部分,它在停靠。我想要从所有XAML到所有代码,所以我可以重复使用这个超过一个地方,有不同的Uri。

但是,当我试着去做同样的事情在代码,我得到一个DirectoryNotFoundException,因为它突然开始试图寻找一个磁盘上的文件夹中,而不是装的像从资源。

  • 如果我载BitmapImage在换,然后创建一个CroppedBitmap在摘要的一切工作。
  • 如果我载BitmapImage在摘要后编写代码,以创建一个CroppedBitmap从它的一切工作。
  • 如果我载BitmapImage在代码, 没有 创建一个CroppedBitmap从它的一切工作。
  • 但是,如果我载BitmapImage在代码 创建一个CroppedBitmap在代码,它试图从文件系统,而不是资源,我得到一个DirectoryNotFoundException.

代码样本如下。我肯定我在做什么蠢事,但是我跑过了整个事情现在的三倍(一次在我的真实程序,一次在测试的应用程序,并且一旦,而写了这个问题),和我有相同结果的所有三次。

对于所有下列代码样本,我已经创建了一个图像文件夹,在我的项目,并加入一个现有的图像的还有被称为"精灵。png",与性质的设定缺省值(建立Action="资源";复制到输出的目录="不复制").


案例1:两BitmapImage和CroppedBitmap在停靠。

<Window x:Class="WpfApplication8.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window1" Height="300" Width="300">
    <Window.Resources>
        <BitmapImage x:Key="fullImage" UriSource="Images/elf.png"/>
        <CroppedBitmap x:Key="croppedImage" Source="{StaticResource fullImage}"
                       SourceRect="0 0 240 320"/>
    </Window.Resources>
    <Image Source="{StaticResource croppedImage}"/>
</Window>

这显示出裁剪的部位,如预期。


案例2:BitmapImage在XAML;CroppedBitmap在代码-在后面。

<Window x:Class="WpfApplication8.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window1" Height="300" Width="300">
    <Window.Resources>
        <BitmapImage x:Key="fullImage" UriSource="Images/elf.png"/>
    </Window.Resources>
    <Image Name="image"/>
</Window>

构造中的代码隐藏:

public Window1()
{
    InitializeComponent();
    var fullImage = (BitmapImage) FindResource("fullImage");
    var croppedImage =
        new CroppedBitmap(fullImage, new Int32Rect(0, 0, 240, 320));
    image.Source = croppedImage;
}

这也显示了裁剪的部位,如预期。


3种情况:BitmapImage在码;没有CroppedBitmap.

public Window1()
{
    InitializeComponent();
    var uri = new Uri("Images/elf.png", UriKind.RelativeOrAbsolute);
    var fullImage = new BitmapImage(uri);
    image.Source = fullImage;
}

这显示了整个位图。这不是我想要的,但不会告诉我,我知道如何写C#码创建合适的Uri和载BitmapImage从一个资源。


案例4:BitmapImage和CroppedBitmap在代码。

    public Window1()
    {
        InitializeComponent();
        var uri = new Uri("Images/elf.png", UriKind.RelativeOrAbsolute);
        var fullImage = new BitmapImage(uri);
        var croppedImage =
            new CroppedBitmap(fullImage, new Int32Rect(0, 0, 240, 320));
        image.Source = croppedImage;
    }

我可以告诉大家,这只是放在一起同样的作品。它使用的代码,我知道将负载一个BitmapImage从资源,和代码,我知道将作物的一部分从一个装BitmapImage。但不知何故,当两个放在一起,它忘记了资源是存在的,并试图从磁盘。我得到以下例外:

  • XamlParseException:"不能创建的实例'Window1'定义在大会'WpfApplication8,Version=于1.0.0.0、文化=中立的,程序=null'.异常已经被通过的目标的一个调用。错误的标记文件'Window1.xaml'线的位置1 13."
    • 内例外: 这样的:"异常已经被通过的目标的一个调用。"
      • 内例外: DirectoryNotFoundException:"不可能找到一部分的道路'C:\svn\WpfApplication8\WpfApplication8\bin\Debug\Images\elf.png'."

内-内外堆的跟踪显示,原来的例外(第DirectoryNotFoundException)正在引发行,例化CroppedBitmap.我不知道为什么那条线将试图读磁盘、或为什么它不工作时为止-as-我可以告诉当XAML。

因为我知道XAML是使用无参构造,我也尝试了下列版本,它应当更接近于XAML实际的作用:

public Window1()
{
    InitializeComponent();
    var uri = new Uri("Images/elf.png", UriKind.RelativeOrAbsolute);
    var fullImage = new BitmapImage();
    fullImage.BeginInit();
    fullImage.UriSource = uri;
    fullImage.EndInit();
    var croppedImage = new CroppedBitmap();
    croppedImage.BeginInit();
    croppedImage.Source = fullImage;
    croppedImage.SourceRect = new Int32Rect(0, 0, 240, 320);
    croppedImage.EndInit();
    image.Source = croppedImage;
}

同样的例外,此时从 croppedImage.EndInit(); 线。

任何想法,我怎么能得到所有代码版本正确地载的资源和作物的图像?发生了什么事在XAML版本那是什么不同?

有帮助吗?

解决方案

魔法被证明是在BitmapImage的 BaseUri 财产。BaseUri显然是用作"目录",UriSource是相对的。

当我BitmapImage正在加载摘BaseUri是被神奇地设定为"包://应用程序:,,,/WpfApplication8;组件/window1.xaml".当我修改的代码片段#4的明确设定fullImage.BaseUri到相同的价值之前创造CroppedBitmap,一切工作。

为什么它的工作从XAML (并且从刚BitmapImage-没有-CroppedBitmap)

那么这个神奇的BaseUri值从何而来?

BaseUri的一部分 IUriContext 接口。IUriContext.BaseUri落在两个地方在WPF组之间,以及我的各种例子,我来打 它们。怪不得我感到困惑。

  • BamlRecordReader.ElementInitialize. 该BAML加载程序自动设定BaseUri随时它加载一元素,实现了IUriContext.这就解释了为什么我的例子#1和第2工作:他们被装载从编BAML资源。
  • 图像。UpdateBaseUri (称为每当源的财产是改变)。这个检查来看看是否源实现IUriContext,如果是,设定其BaseUri.这就解释了为什么我的例子#3的工作:推动BitmapImage入GUI迫使它得到正确的搜索的道路。

这只看起来像在EXE资源时BaseUri是集到魔法包://URI。没有(作为发生的时候一切都是建立在代码并不推入GUI),它只是看起来在磁盘上。

修复

如上面所指出的,我能硬代码BaseUri.但 BaseUriHelper 类提供一个更好的解决:

fullImage.BaseUri = BaseUriHelper.GetBaseUri(this);

这套fullImage有相同的BaseUri窗口(this).如果这样做之前创造CroppedBitmap,一切工作。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top