C# 在代码中设置 WPF 图片源
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/350027/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Setting WPF image source in code
提问by Torbj?rn
I'm trying to set a WPF image's source in code. The image is embedded as a resource in the project. By looking at examples I've come up with the below code. For some reason it doesn't work - the image does not show up.
我正在尝试在代码中设置 WPF 图像的源。图像作为资源嵌入到项目中。通过查看示例,我想出了以下代码。由于某种原因它不起作用 - 图像不显示。
By debugging I can see that the stream contains the image data. So what's wrong?
通过调试,我可以看到流包含图像数据。那么怎么了?
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;
The icon is defined something like this: <Image x:Name="_icon" Width="16" Height="16" />
图标定义如下: <Image x:Name="_icon" Width="16" Height="16" />
采纳答案by Jared Harley
After having the same problem as you and doing some reading, I discovered the solution - Pack URIs.
在遇到与您相同的问题并进行一些阅读后,我发现了解决方案 - Pack URIs。
I did the following in code:
我在代码中做了以下事情:
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;
Or shorter, by using another BitmapImage constructor:
或者更短,通过使用另一个 BitmapImage 构造函数:
finalImage.Source = new BitmapImage(
new Uri("pack://application:,,,/AssemblyName;component/Resources/logo.png"));
The URI is broken out into parts:
URI 分为几个部分:
- Authority:
application:///
Path: The name of a resource file that is compiled into a referenced assembly. The path must conform to the following format:
AssemblyShortName[;Version][;PublicKey];component/Path
- AssemblyShortName: the short name for the referenced assembly.
- ;Version [optional]: the version of the referenced assembly that contains the resource file. This is used when two or more referenced assemblies with the same short name are loaded.
- ;PublicKey [optional]: the public key that was used to sign the referenced assembly. This is used when two or more referenced assemblies with the same short name are loaded.
- ;component: specifies that the assembly being referred to is referenced from the local assembly.
- /Path: the name of the resource file, including its path, relative to the root of the referenced assembly's project folder.
- 权威:
application:///
路径:编译为引用程序集的资源文件的名称。路径必须符合以下格式:
AssemblyShortName[;Version][;PublicKey];component/Path
- AssemblyShortName:引用程序集的短名称。
- ;Version [可选]:包含资源文件的引用程序集的版本。当加载两个或多个具有相同短名称的引用程序集时使用。
- ;PublicKey [可选]:用于对引用的程序集进行签名的公钥。当加载了两个或多个具有相同短名称的引用程序集时使用。
- ;component:指定被引用的程序集是从本地程序集引用的。
- /Path:资源文件的名称,包括其路径,相对于引用程序集的项目文件夹的根目录。
The three slashes after application:
have to be replaced with commas:
后面的三个斜杠application:
必须用逗号替换:
Note: The authority component of a pack URI is an embedded URI that points to a package and must conform to RFC 2396. Additionally, the "/" character must be replaced with the "," character, and reserved characters such as "%" and "?" must be escaped. See the OPC for details.
注意:包 URI 的授权组件是指向包的嵌入 URI,必须符合 RFC 2396。此外,“/”字符必须替换为“,”字符,以及“%”等保留字符和 ”?” 必须逃脱。有关详细信息,请参阅 OPC。
And of course, make sure you set the build action on your image to Resource
.
当然,请确保将图像上的构建操作设置为Resource
.
回答by Arcturus
Put the frame in a VisualBrush:
将框架放在 VisualBrush 中:
VisualBrush brush = new VisualBrush { TileMode = TileMode.None };
brush.Visual = frame;
brush.AlignmentX = AlignmentX.Center;
brush.AlignmentY = AlignmentY.Center;
brush.Stretch = Stretch.Uniform;
Put the VisualBrush in GeometryDrawing
将 VisualBrush 放入 GeometryDrawing
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;
Now put the GeometryDrawing in a DrawingImage:
现在将 GeometryDrawing 放在 DrawingImage 中:
new DrawingImage(drawing);
Place this on your source of the image, and voilà!
把它放在你的图像来源上,瞧!
You could do it a lot easier though:
不过,您可以更轻松地做到这一点:
<Image>
<Image.Source>
<BitmapImage UriSource="/yourassembly;component/YourImage.PNG"></BitmapImage>
</Image.Source>
</Image>
And in code:
在代码中:
BitmapImage image = new BitmapImage { UriSource="/yourassembly;component/YourImage.PNG" };
回答by Andrew Myhre
Have you tried:
你有没有尝试过:
Assembly asm = Assembly.GetExecutingAssembly();
Stream iconStream = asm.GetManifestResourceStream("SomeImage.png");
BitmapImage bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.StreamSource = iconStream;
bitmap.EndInit();
_icon.Source = bitmap;
回答by awe
Here is an example that sets the image path dynamically (image located somewhere on disc rather than build as resource):
这是一个动态设置图像路径的示例(图像位于光盘上的某处而不是作为资源构建):
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;
}
Reflections on Icons...
对图标的思考...
First thought, you would think that the Icon property can only contain an image. But it can actually contain anything! I discovered this by accident when I programmatically tried to set the Image
property directly to a string with the path to an image. The result was that it did not show the image, but the actual text of the path!
首先想到的是,您会认为 Icon 属性只能包含一个图像。但它实际上可以包含任何东西!当我以编程方式尝试将Image
属性直接设置为带有图像路径的字符串时,我偶然发现了这一点。结果是它没有显示图像,而是路径的实际文本!
This leads to an alternative to not have to make an image for the icon, but use text with a symbol font instead to display a simple "icon". The following example uses the Wingdings fontwhich contains a "floppydisk" symbol. This symbol is really the character <
, which has special meaning in XAML, so we have to use the encoded version <
instead. This works like a dream! The following shows a floppydisk symbol as an icon on the menu item:
这导致不必为图标制作图像,而是使用带有符号字体的文本来显示简单的“图标”。以下示例使用包含“软盘”符号的Wingdings 字体。这个符号实际上是字符<
,它在 XAML 中具有特殊含义,因此我们必须改用编码版本<
。这就像做梦一样!下面将软盘符号显示为菜单项上的图标:
<MenuItem Name="mnuFileSave" Header="Save" Command="ApplicationCommands.Save">
<MenuItem.Icon>
<Label VerticalAlignment="Center" HorizontalAlignment="Center" FontFamily="Wingdings"><</Label>
</MenuItem.Icon>
</MenuItem>
回答by Simon
var uriSource = new Uri(@"/WpfApplication1;component/Images/Untitled.png", UriKind.Relative);
foo.Source = new BitmapImage(uriSource);
This will load a image called "Untitled.png" in a folder called "Images" with its "Build Action" set to "Resource" in an assembly called "WpfApplication1".
这将在名为“Images”的文件夹中加载名为“Untitled.png”的图像,在名为“WpfApplication1”的程序集中,其“构建操作”设置为“资源”。
回答by Alex B
This is a bit less code and can be done in a single line.
这是一个少一点的代码,可以在一行中完成。
string packUri = "pack://application:,,,/AssemblyName;component/Images/icon.png";
_image.Source = new ImageSourceConverter().ConvertFromString(packUri) as ImageSource;
回答by Mark Mullin
There's also a simpler way. If the image is loaded as a resource in the XAML, and the code in question is the codebehind for that XAML:
还有一个更简单的方法。如果图像作为 XAML 中的资源加载,并且有问题的代码是该 XAML 的代码隐藏:
Here's the resource dictionary for a XAML file - the only line you care about is the ImageBrush with the key "PosterBrush" - the rest of the code is just to show context
这是 XAML 文件的资源字典——你关心的唯一一行是带有“PosterBrush”键的 ImageBrush——其余的代码只是为了显示上下文
<UserControl.Resources>
<ResourceDictionary>
<ImageBrush x:Key="PosterBrush" ImageSource="..\Resources\Images\EmptyPoster.jpg" Stretch="UniformToFill"/>
</ResourceDictionary>
</UserControl.Resources>
Now, in the code behind, you can just do this
现在,在后面的代码中,你可以这样做
ImageBrush posterBrush = (ImageBrush)Resources["PosterBrush"];
回答by Siarhei Kuchuk
How to load an image from embedded in resource icons and images (corrected version of Arcturus):
如何从嵌入的资源图标和图像中加载图像(Arcturus 的修正版本):
Suppose you want to add a button with an image. What should you do?
假设您要添加一个带有图像的按钮。你该怎么办?
- Add to project folder icons and put image ClickMe.png here
- In properties of 'ClickMe.png', set 'BuildAction' to 'Resource'
- Suppose your compiled assembly name is 'Company.ProductAssembly.dll'.
Now it's time to load our image in 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>
- 添加到项目文件夹图标并将图像 ClickMe.png 放在这里
- 在“ClickMe.png”的属性中,将“BuildAction”设置为“Resource”
- 假设您编译的程序集名称是“Company.ProductAssembly.dll”。
现在是时候在 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.
完毕。
回答by Siarhei Kuchuk
If you already have a stream and know the format, you can use something like this:
如果你已经有一个流并且知道格式,你可以使用这样的东西:
static ImageSource PngStreamToImageSource (Stream pngStream) {
var decoder = new PngBitmapDecoder(pngStream,
BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
return decoder.Frames[0];
}
回答by JoanComasFdz
I am a new to WPF, but not in .NET.
我是 WPF 的新手,但不是 .NET。
I have spent five hours trying to add a PNG file to a "WPF Custom Control Library Project" in .NET 3.5 (Visual Studio 2010) and setting it as a background of an image-inherited control.
我花了五个小时试图将 PNG 文件添加到 .NET 3.5 (Visual Studio 2010) 中的“WPF 自定义控件库项目”,并将其设置为图像继承控件的背景。
Nothing relative with URIs worked. I can not imagine why there is no method to get a URI from a resource file, through IntelliSense, maybe as:
没有任何与 URI 相关的工作。我无法想象为什么没有通过 IntelliSense 从资源文件中获取 URI 的方法,可能是:
Properties.Resources.ResourceManager.GetURI("my_image");
I've tried a lot of URIs and played with ResourceManager, and Assembly's GetManifest methods, but all there were exceptions or NULL values.
我已经尝试了很多 URI 并使用了 ResourceManager 和 Assembly 的 GetManifest 方法,但都存在异常或 NULL 值。
Here I pot the code that worked for me:
在这里,我编写了对我有用的代码:
// 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;