C#-如何从XAML访问动态图像/位图源?

时间:2018-12-17 22:16:38

标签: c# wpf xaml resources runtime

在我的C#项目中,我有一个图像列表,这些图像是在exe中编译的资源:

/Pics/Image1.png /Pics/Image2.png /Pics/Image3.png ...

在我的代码中,我处理图像以使其与应用程序的主题匹配。我遇到的问题是,我试图找出一种简单的方法来以XAML语法访问这些已处理的图像。

这通常是我访问资源图像(预处理)的方式:

<Image Source="/Pics/Image1.png" />

所以我真的很想以类似的方式访问这些处理过的图像。

我尝试过这样的静态字典:

<Image Source="{x:Static local:Theme.Images.ImageDictionary[/Pics/Image1.png]}" />

但是这引发了一个错误,因为它不喜欢“ .png”,我还无法使用字典键来实现。更不用说这看起来真的很丑。

理想情况下,我希望能够“替换”资源引用,或在运行时创建资源(例如PicsProcessed/Image1.png),但一直无法找到一种在运行中添加或修改资源的方法通过编程C#应用程序。

任何建议都非常感谢-谢谢!

2 个答案:

答案 0 :(得分:0)

您是否尝试过创建Bitmap并将其设置为图像source?我认为这应该很容易。给图片起个名字,例如theImage。您不能在未命名的情况下引用该图像。 请尝试以下操作:

string path="/Pics/Image3.png";//path to the image
var bitmapImage=new Bitmap(new Uri(path));
theImage.source=bitmapImage;//set the bitmap as the source.

不过,还有其他方法可以实现此目的。希望这会有所帮助吗?

答案 1 :(得分:0)

过了几天,但我想出了解决方案!

在相同的解决方案中,我将所有图像移到了另一个C#项目中,并设置为作为类库DLL文件进行编译,该文件名为DynamicResources.dll(“项目”设置中的程序集名称为“ DynamicResources”)。该项目被添加为对主项目的引用。这样,我可以在XAML中访问图像-整洁:

<Image Source="/DynamicResources;component/pics/image1.png" />

然后在主项目的构建后事件中,我重命名已编译的.dll,以便它在启动时不会被主.exe二进制文件加载

copy "$(TargetDir)DynamicResources.dll" "$(TargetDir)DynamicResources.temp" 
del "$(TargetDir)DynamicResources.dll"

然后,我使用了一个名为Mono.Cecil的第三方库来加载DynamicResources.temp文件(DLL格式),替换资源,将其写回到内存中,然后告诉应用程序进行加载:

public static void UpdateAssembly()
{
    string dllFile = "DynamicResources.temp";
    string dllNamespace = "DynamicResources";

    var asm = AssemblyDefinition.ReadAssembly(dllFile);            
    var module = asm.Modules.FirstOrDefault();
    var resources = module.Resources;
    var dllResource = (EmbeddedResource)(resources.FirstOrDefault());
    var dllResourceReader = new ResourceReader(dllResource.GetResourceStream());
    var newResourceOutputStream = new MemoryStream();
    var newResourceWriter = new ResourceWriter(newResourceOutputStream);
    foreach (DictionaryEntry dllResourceEntry in dllResourceReader)
    {
       var image = (BitmapSource)new ImageSourceConverter().ConvertFrom(dllResourceEntry.Value);

       Color foreground = (Color)ColorConverter.ConvertFromString("#FFFFFF");
       var processed = (WriteableBitmap)ColorizeImage(image, foreground); // Your image processing function ?

       newResourceWriter.AddResource(dllResourceEntry.Key.ToString(), BitmapToByte(processed));       
    }
    newResourceWriter.Close();

    var newResource = new EmbeddedResource(dllResource.Name, dllResource.Attributes, newResourceOutputStream.ToArray());
    module.Resources.Remove(dllResource);
    module.Resources.Add(newResource);

    var woutput = new MemoryStream();

    asm.Write(woutput);
    var doutput = woutput.ToArray();
    Assembly assembly = Assembly.Load(doutput);
}
public static MemoryStream BitmapToByte(BitmapSource bitmapSource)
{
    var encoder = new System.Windows.Media.Imaging.PngBitmapEncoder();
    var frame = System.Windows.Media.Imaging.BitmapFrame.Create(bitmapSource);
    encoder.Frames.Add(frame);
    var stream = new MemoryStream();
    encoder.Save(stream);
    return stream;
}
public static void AttachAssembly(string myAsmFileName)
{
    Assembly assembly = Assembly.LoadFile(AppDomain.CurrentDomain.BaseDirectory + myAsmFileName); // LoadFrom
    AppDomain.CurrentDomain.Load(assembly.GetName());
}

重要说明:遍历资源时,它们变为小写,因此您必须使用小写的文件名和文件夹名。