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


当前回答

很简单:

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

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

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

其他回答

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

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

还有一种更简单的方法。如果图像在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"];

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

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

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

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

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

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字体。这个符号实际上是字符<,它在XAML中有特殊的含义,所以我们必须使用编码版本&lt;代替。这就像做梦一样!下面将软盘符号显示为菜单项上的图标:

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