在代码中设置WPF图像源

我试图在代码中设置WPF图像的源代码。图像作为资源嵌入到项目中。通过查看示例,我提出了下面的代码。由于某种原因,它不工作-图像不显示。

通过调试,我可以看到流包含图像数据。怎么了?

Assembly asm = Assembly.GetExecutingAssembly();
Stream iconStream = asm.GetManifestResourceStream("SomeImage.png");
PngBitmapDecoder iconDecoder = new PngBitmapDecoder(iconStream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
ImageSource iconSource = iconDecoder.Frames[0];
_icon.Source = iconSource;

图标的定义如下:<Image x:Name="_icon" Width="16" Height="16" />

613221 次浏览

将框架放在VisualBrush中:

VisualBrush brush = new VisualBrush { TileMode = TileMode.None };


brush.Visual = frame;


brush.AlignmentX = AlignmentX.Center;
brush.AlignmentY = AlignmentY.Center;
brush.Stretch = Stretch.Uniform;

把VisualBrush放在几何绘图中

GeometryDrawing drawing = new GeometryDrawing();


drawing.Brush = brush;


// Brush this in 1, 1 ratio
RectangleGeometry rect = new RectangleGeometry { Rect = new Rect(0, 0, 1, 1) };
drawing.Geometry = rect;

现在将几何绘图放在DrawingImage中:

new DrawingImage(drawing);

把这个放在你的图片源上,然后是voilà!

你可以做得更简单:

<Image>
<Image.Source>
<BitmapImage UriSource="/yourassembly;component/YourImage.PNG"></BitmapImage>
</Image.Source>
</Image>

在代码中:

BitmapImage image = new BitmapImage { UriSource="/yourassembly;component/YourImage.PNG" };

你有没有试过:

Assembly asm = Assembly.GetExecutingAssembly();
Stream iconStream = asm.GetManifestResourceStream("SomeImage.png");
BitmapImage bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.StreamSource = iconStream;
bitmap.EndInit();
_icon.Source = bitmap;

下面是一个动态设置映像路径的例子(映像位于磁盘上的某个位置,而不是作为资源构建):

if (File.Exists(imagePath))
{
// Create image element to set as icon on the menu element
Image icon = new Image();
BitmapImage bmImage = new BitmapImage();
bmImage.BeginInit();
bmImage.UriSource = new Uri(imagePath, UriKind.Absolute);
bmImage.EndInit();
icon.Source = bmImage;
icon.MaxWidth = 25;
item.Icon = icon;
}

关于图标的思考……

首先,您可能认为Icon属性只能包含图像。但它实际上可以包含任何东西!当我通过编程方式试图将Image属性直接设置为包含图像路径的字符串时,我偶然发现了这一点。结果是它没有显示图像,而是显示路径的实际文本!

这导致了一种不必为图标制作图像的替代方案,而是使用带有符号字体的文本来显示简单的“图标”。下面的例子使用了闹酒狂欢字体,它包含一个"floppydisk"符号。这个符号实际上是字符<,它在XAML中有特殊的含义,所以我们必须使用编码版本&lt;来代替。这就像做梦一样!下面将软盘符号显示为菜单项上的图标:

<MenuItem Name="mnuFileSave" Header="Save" Command="ApplicationCommands.Save">
<MenuItem.Icon>
<Label VerticalAlignment="Center" HorizontalAlignment="Center" FontFamily="Wingdings">&lt;</Label>
</MenuItem.Icon>
</MenuItem>
var uriSource = new Uri(@"/WpfApplication1;component/Images/Untitled.png", UriKind.Relative);
foo.Source = new BitmapImage(uriSource);

这将在名为“WpfApplication1”的程序集中加载名为“Untitled.png”的图像到名为“Images”的文件夹中,其“Build Action”设置为“Resource”。

在和你有同样的问题并做了一些阅读之后,我发现了解决方案- 包uri

我在代码中做了以下事情:

Image finalImage = new Image();
finalImage.Width = 80;
...
BitmapImage logo = new BitmapImage();
logo.BeginInit();
logo.UriSource = new Uri("pack://application:,,,/AssemblyName;component/Resources/logo.png");
logo.EndInit();
...
finalImage.Source = logo;

或者更短,通过使用另一个BitmapImage构造函数:

finalImage.Source = new BitmapImage(
new Uri("pack://application:,,,/AssemblyName;component/Resources/logo.png"));

URI被分成几个部分:

  • 权威:application:///
  • Path:被编译成引用程序集的资源文件的名称。路径必须遵循以下格式:AssemblyShortName[;Version][;PublicKey];component/Path

    • AssemblyShortName:引用程序集的短名称。
    • 版本[可选]:包含资源文件的引用程序集的版本。当加载两个或多个具有相同短名称的引用程序集时使用。
    • PublicKey[可选]:用于为引用的程序集签名的公钥。当加载两个或多个具有相同短名称的引用程序集时使用。
    • component:指定被引用的程序集是从本地程序集引用的。
    • /Path:资源文件的名称,包括其相对于引用程序集的项目文件夹根的路径。
    • 李< / ul > < / >

    application:后面的三个斜杠必须用逗号替换:

    注意:包URI的授权组件 是一个嵌入式URI,指向 包装,必须符合RFC 2396。 此外,“/”字符必须 替换为“,”字符, 以及保留字符,如“%” "?"必须转义。查看OPC 对细节。< / p >

    当然,确保将映像上的构建操作设置为Resource

这是一个更少的代码,可以在一行中完成。

string packUri = "pack://application:,,,/AssemblyName;component/Images/icon.png";
_image.Source = new ImageSourceConverter().ConvertFromString(packUri) as ImageSource;

还有一种更简单的方法。如果图像在XAML中作为资源加载,并且所讨论的代码是该XAML的幕后代码:

下面是一个XAML文件的资源字典——你唯一关心的一行是ImageBrush,键为“PosterBrush”——其余的代码只是用来显示上下文

<UserControl.Resources>
<ResourceDictionary>
<ImageBrush x:Key="PosterBrush" ImageSource="..\Resources\Images\EmptyPoster.jpg" Stretch="UniformToFill"/>


</ResourceDictionary>
</UserControl.Resources>

在后面的代码中,你可以这样做

ImageBrush posterBrush = (ImageBrush)Resources["PosterBrush"];

如何从嵌入的资源图标和图像(校正版本的Arcturus)加载图像:

假设您想添加一个带有图像的按钮。你该怎么办?

  1. 添加到项目文件夹图标,并将图像ClickMe.png放在这里
  2. 在“ClickMe.png”的属性中,将“BuildAction”设置为“Resource”
  3. 假设编译后的程序集名称是'Company.ProductAssembly.dll'。
  4. 现在是时候在XAML中加载我们的图像了

    <Button Width="200" Height="70">
    <Button.Content>
    <StackPanel>
    <Image Width="20" Height="20">
    <Image.Source>
    <BitmapImage UriSource="/Company.ProductAssembly;component/Icons/ClickMe.png"></BitmapImage>
    </Image.Source>
    </Image>
    <TextBlock HorizontalAlignment="Center">Click me!</TextBlock>
    </StackPanel>
    </Button.Content>
    </Button>
    

Done.

如果你已经有了一个流,并且知道它的格式,你可以使用这样的东西:

static ImageSource PngStreamToImageSource (Stream pngStream) {
var decoder = new PngBitmapDecoder(pngStream,
BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
return decoder.Frames[0];
}

我是WPF的新手,但不熟悉。net。

我花了五个小时尝试在。net 3.5 (Visual Studio 2010)中添加一个PNG文件到“WPF自定义控件库项目”,并将其设置为图像继承控件的背景。

与uri相关的任何东西都不起作用。我无法想象为什么没有方法从资源文件中获取URI,通过智能感知,可能是:

Properties.Resources.ResourceManager.GetURI("my_image");

我已经尝试了很多uri和ResourceManager,以及Assembly的GetManifest方法,但都有异常或NULL值。

在这里我罐的代码,为我工作:

// Convert the image in resources to a Stream
Stream ms = new MemoryStream()
Properties.Resources.MyImage.Save(ms, ImageFormat.Png);


// Create a BitmapImage with the stream.
BitmapImage bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.StreamSource = ms;
bitmap.EndInit();


// Set as source
Source = bitmap;

还有一种更简单的方法。如果图像在XAML中作为资源加载,并且所讨论的代码是该XAML内容的幕后代码:

Uri iconUri = new Uri("pack://application:,,,/ImageNAme.ico", UriKind.RelativeOrAbsolute);
NotifyIcon.Icon = BitmapFrame.Create(iconUri);

很简单:

要动态设置菜单项的图像,只需执行以下操作:

MyMenuItem.ImageSource =
new BitmapImage(new Uri("Resource/icon.ico",UriKind.Relative));

...而“icon.ico”可以位于任何地方(目前它位于“资源”目录中),并且必须链接为资源…

您还可以将其缩减为一行。这是我用来设置主窗口图标的代码。它假定.ico文件被标记为Content并被复制到输出目录。

 this.Icon = new BitmapImage(new Uri("Icon.ico", UriKind.Relative));

最简单的方法:

var uriSource = new Uri("image path here");
image1.Source = new BitmapImage(uriSource);

你只是漏了一点。

要从任何程序集获取嵌入式资源,你必须像我在这里提到的那样,用你的文件名提到程序集名称:

Assembly asm = Assembly.GetExecutingAssembly();
Stream iconStream = asm.GetManifestResourceStream(asm.GetName().Name + "." + "Desert.jpg");
BitmapImage bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.StreamSource = iconStream;
bitmap.EndInit();
image1.Source = bitmap;

这是我的方式:

internal static class ResourceAccessor
{
public static Uri Get(string resourcePath)
{
var uri = string.Format(
"pack://application:,,,/{0};component/{1}"
, Assembly.GetExecutingAssembly().GetName().Name
, resourcePath
);


return new Uri(uri);
}
}

用法:

new BitmapImage(ResourceAccessor.Get("Images/1.png"))

如果你的图像存储在ResourceDictionary中,你只需要一行代码就可以做到:

MyImage.Source = MyImage.FindResource("MyImageKeyDictionary") as ImageSource;

如果你想把它定位在可执行文件旁边(相对于可执行文件)

img.Source = new BitmapImage(new Uri(AppDomain.CurrentDomain.BaseDirectory + @"\Images\image.jpg", UriKind.Absolute));

Force选择UriKind将是正确的:

Image.Source = new BitmapImage(new Uri("Resources/processed.png", UriKind.Relative));

UriKind选项:

UriKind.Relative // relative path
UriKind.Absolute // exactly path