" /> "> " />
ChatGPT解决这个技术问题 Extra ChatGPT

在代码中设置 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" />

如果映像位于本地驱动器上,则 XAML 中的 <Image Source="some_fully_qualified_path"> 永远不会失败。
@LaurieSearn 的重点是我们不知道路径并且需要代码来确定它。作为 Windows GUI 编程的新手,我不得不承认 WinForms 似乎比这个 XAML 废话更有吸引力。

C
Clemens

在遇到与您相同的问题并阅读后,我发现了解决方案 - Pack URIs

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

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 分为几部分:

权限:应用程序:///

路径:编译成引用程序集的资源文件的名称。路径必须符合以下格式: AssemblyShortName[;Version][;PublicKey];component/Path AssemblyShortName:被引用程序集的短名称。 ;Version [可选]:包含资源文件的引用程序集的版本。这在加载两个或多个具有相同短名称的引用程序集时使用。 ;PublicKey [可选]:用于签署引用程序集的公钥。这在加载两个或多个具有相同短名称的引用程序集时使用。 ;component:指定被引用的程序集是从本地程序集引用的。 /Path:资源文件的名称,包括其路径,相对于所引用程序集的项目文件夹的根目录。

AssemblyShortName:被引用程序集的短名称。

;Version [可选]:包含资源文件的引用程序集的版本。这在加载两个或多个具有相同短名称的引用程序集时使用。

;PublicKey [可选]:用于签署引用程序集的公钥。这在加载两个或多个具有相同短名称的引用程序集时使用。

;component:指定被引用的程序集是从本地程序集引用的。

/Path:资源文件的名称,包括其路径,相对于所引用程序集的项目文件夹的根目录。

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

注意:包 URI 的授权组件是一个嵌入式 URI,它指向一个包,并且必须符合 RFC 2396。此外,“/”字符必须替换为“,”字符和保留字符,例如“%”和 ”?”必须逃脱。有关详细信息,请参阅 OPC。

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


是的,这是我经过反复试验后找到的解决方案。感谢您的详尽解释。回答采纳!
我不知道为什么需要这样做,为什么其他答案对我不起作用......
这个问题和其他问题中的其他答案也对我不起作用。这个完美无缺。谢谢。
好的,但是 XAML 解析器是否使用某些方法或类将简单路径字符串转换为 ImageSource?我们不能用那个吗?
我经常看到这个片段被复制到其他帖子中,人们通常会忽略 BitmapImage(Uri) 构造函数的存在,这有助于避免调用 BeginInit 和 EndInit。我在这里添加了它。
M
Maksymilian Mulawa
var uriSource = new Uri(@"/WpfApplication1;component/Images/Untitled.png", UriKind.Relative);
foo.Source = new BitmapImage(uriSource);

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


感谢那。一个让我成为 wpf 菜鸟的问题,必须将图像标记为资源才能正常工作。
这个解决方案给了我一个例外,所以我尝试了 Jared Harley 的解决方案,它奏效了......
最重要的是“UriKind.RelativeOrAbsolute”——其他例子总是抛出异常
var uriSource = new Uri("Images/Untitled.png", UriKind.Relative); 就足够了
此解决方案对我不起作用,但是将 pack://application:,,, 附加到 Uri 可以。
A
Alex B

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

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

这绝对是最好的答案,利用 .NETs 自己的实现
如果我们需要设置图像的高度和宽度,即icon.png怎么办?因为通过使用 _image.height 和 _image.width 它设置图像窗口而不是实际图像,即 icon.png。
A
Alexander Farber

很容易:

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

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

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


更短=更好。我不得不将它设置为 @"/folder/image.png" 但是它工作正常。谢谢!
当我分配图像源时,它只是显示为空白:(
@HaloMediaz 路径可能是错误的....例如,您有 Resources 但您可以编写它 Resource
这对我有用,而且比其他答案中的绝对 URI 要简单得多。
P
Peter Mortensen

最简单的方法:

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

M
Manfred

这是我的方式:

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"))

很好的解决方案。无需关心程序集名称即可轻松返回字符串并使用 Binding。
P
Payson Welch

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

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

A
Andrew Myhre

你有没有尝试过:

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

P
Peter Mortensen

如果您的图像存储在 ResourceDictionary 中,则只需一行代码即可:

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

3
3 revs, 2 users 79%

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

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 属性直接设置为带有图像路径的字符串时,我偶然发现了这一点。结果是它没有显示图像,而是路径的实际文本!

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

<MenuItem Name="mnuFileSave" Header="Save" Command="ApplicationCommands.Save">
  <MenuItem.Icon>
    <Label VerticalAlignment="Center" HorizontalAlignment="Center" FontFamily="Wingdings">&lt;</Label>
  </MenuItem.Icon>
</MenuItem>

问题:“图像作为资源嵌入到项目中”,回答:“这是一个示例 [for an image] 位于磁盘上的某个位置,而不是作为资源构建”。
3
3 revs, 3 users 70%

还有一种更简单的方法。如果图像作为 XAML 中的资源加载,并且相关代码是该 XAML 内容的代码隐藏:

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

P
Peter Mortensen

将框架放入 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

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;

现在将 GeometryDrawing 放入 DrawingImage:

new DrawingImage(drawing);

把它放在你的图片来源上,瞧!

不过,您可以更轻松地做到这一点:

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

在代码中:

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

哈哈!为什么当你第一次让它变得困难时让它变得容易:)我会在我接受之前尝试你的简单解决方案......
实际上,这对我一点帮助都没有。也许我很愚蠢:(现在没有时间更仔细地看(宠物项目)。当我回到它时想要更多答案:)
P
Peter Mortensen

还有一种更简单的方法。如果图像作为 XAML 中的资源加载,并且相关代码是该 XAML 的代码隐藏:

这是 XAML 文件的资源字典 - 您关心的唯一行是带有键“PosterBrush”的 ImageBrush - 其余代码只是为了显示上下文

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

        </ResourceDictionary>
    </UserControl.Resources>

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

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

P
Peter Mortensen

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

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

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

完毕。


P
Peter Mortensen

我是 WPF 的新手,但不是 .NET。

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

与 URI 相关的任何东西都不起作用。我无法想象为什么没有通过 IntelliSense 从资源文件中获取 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;

我认为问题在于 WPF 不“喜欢”将资源放入 resx 文件的传统方法。相反,您应该将图像直接添加到您的项目中并将其 Build Action 属性设置为 Resource。我不知道这两种方法之间有什么区别(就物理文件格式而言)。
确保构建操作是内容
P
Peter Mortensen

你只是错过了一点。

要从任何程序集中获取嵌入式资源,您必须在文件名中提及程序集名称,正如我在这里提到的:

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;

WPF 中似乎不存在 BeginInit()。
可查看以下链接 msdn.microsoft.com/en-us/library/…
佚名

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

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

D
Donovan Phoenix

如果您想在可执行文件旁边找到它(相对于可执行文件)

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

V
VinaCaptcha

强制选择 UriKind 将是正确的:

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

UriKind 选项:

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