C# 在代码中设置WPF图像源

C# 在代码中设置WPF图像源,c#,.net,wpf,image,C#,.net,Wpf,Image,我试图在代码中设置WPF映像的源代码。图像作为资源嵌入到项目中。通过查看示例,我得出了以下代码。由于某种原因,它无法工作-图像无法显示 通过调试,我可以看到流包含图像数据。那怎么了 Assembly asm = Assembly.GetExecutingAssembly(); Stream iconStream = asm.GetManifestResourceStream("SomeImage.png"); PngBitmapDecoder iconDecoder = new PngBitma

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

图标的定义如下:

将框架放入可视化画笔中:

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;
现在将几何图形放入DrawingImage中:

new DrawingImage(drawing);
把这个放在你的图片来源上,瞧

不过,您可以做得简单得多:

<Image>
    <Image.Source>
        <BitmapImage UriSource="/yourassembly;component/YourImage.PNG"></BitmapImage>
    </Image.Source>
</Image>
您是否尝试过:

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

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

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

这导致了一种替代方法,即不必为图标制作图像,而是使用带有符号字体的文本来显示简单的“图标”。以下示例使用包含“floppydisk”符号的。此符号实际上就是字符


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

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

我在代码中执行了以下操作:

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];组件/路径

    • AssemblyShortName:引用程序集的短名称
    • );版本[可选]:包含资源文件的引用程序集的版本。当加载两个或多个具有相同短名称的引用程序集时,将使用此选项
    • );公钥[可选]:用于对引用的程序集进行签名的公钥。当加载两个或多个具有相同短名称的引用程序集时,将使用此选项
    • );组件:指定从本地程序集引用要引用的程序集
    • /路径:资源文件的名称,包括其路径,相对于被引用程序集的项目文件夹的根
应用程序:
后的三个斜杠必须替换为逗号:

注意:包URI的授权组件 是一个嵌入式URI,指向 包装必须符合RFC 2396的要求。 此外,必须使用“/”字符 替换为“,”字符, 和保留字符,如“%” 而“?”必须逃逸。参见OPC 详情请参阅


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

这是一个代码较少的操作,可以在一行中完成

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

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

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

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

        </ResourceDictionary>
    </UserControl.Resources>

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

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

  • 添加到项目文件夹图标并将图像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>
    
    
    点击我!
    

  • 完成。

    如果您已经有一个流,并且知道其格式,您可以使用以下内容:

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

    我是WPF的新手,但不在.NET中

    我花了五个小时试图将PNG文件添加到.NET3.5(VisualStudio2010)中的“WPF自定义控件库项目”中,并将其设置为图像继承控件的背景

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

    Properties.Resources.ResourceManager.GetURI("my_image");
    
    我尝试了很多URI,并使用了ResourceManager和Assembly的GetManifest方法,但都存在异常或空值

    在这里,我编写了适用于我的代码:

    // 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文件被标记为内容,并且正在复制到输出目录

     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;
    

    如果要将其定位在可执行文件旁边(相对于可执行文件),请参见


    英雄联盟当你第一次能使它变得困难时,为什么要使它变得容易呢?)我来试试你的简单解决办法
    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"))
    
    MyImage.Source = MyImage.FindResource("MyImageKeyDictionary") as ImageSource;
    
    img.Source = new BitmapImage(new Uri(AppDomain.CurrentDomain.BaseDirectory + @"\Images\image.jpg", UriKind.Absolute));