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

在我的 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# 应用程序中添加或修改资源的方法。

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


慕沐林林
浏览 197回答 2
2回答

DIEA

花了几天时间,但我想出了一个解决方案!我将所有图像移动到同一解决方案中的另一个 C# 项目中,设置为编译为名为 DynamicResources.dll 的类库 DLL 文件(项目设置中的程序集名称为“DynamicResources”)。添加此项目作为对主项目的引用。因此,我可以访问 XAML 中的图像 - 干净整洁:<Image Source="/DynamicResources;component/pics/image1.png" />然后在主项目的构建后事件中,我重命名已编译的 .dll,这样它就不会在启动时被主 .exe 二进制文件加载:copy "$(TargetDir)DynamicResources.dll" "$(TargetDir)DynamicResources.temp"&nbsp;del "$(TargetDir)DynamicResources.dll"然后我使用了一个名为 Mono.Cecil 的第三方库来加载 DynamicResources.temp 文件(DLL 格式),替换资源,将其写回内存,然后告诉应用程序加载它:public static void UpdateAssembly(){&nbsp; &nbsp; string dllFile = "DynamicResources.temp";&nbsp; &nbsp; string dllNamespace = "DynamicResources";&nbsp; &nbsp; var asm = AssemblyDefinition.ReadAssembly(dllFile);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp; var module = asm.Modules.FirstOrDefault();&nbsp; &nbsp; var resources = module.Resources;&nbsp; &nbsp; var dllResource = (EmbeddedResource)(resources.FirstOrDefault());&nbsp; &nbsp; var dllResourceReader = new ResourceReader(dllResource.GetResourceStream());&nbsp; &nbsp; var newResourceOutputStream = new MemoryStream();&nbsp; &nbsp; var newResourceWriter = new ResourceWriter(newResourceOutputStream);&nbsp; &nbsp; foreach (DictionaryEntry dllResourceEntry in dllResourceReader)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp;var image = (BitmapSource)new ImageSourceConverter().ConvertFrom(dllResourceEntry.Value);&nbsp; &nbsp; &nbsp; &nbsp;Color foreground = (Color)ColorConverter.ConvertFromString("#FFFFFF");&nbsp; &nbsp; &nbsp; &nbsp;var processed = (WriteableBitmap)ColorizeImage(image, foreground); // Your image processing function ?&nbsp; &nbsp; &nbsp; &nbsp;newResourceWriter.AddResource(dllResourceEntry.Key.ToString(), BitmapToByte(processed));&nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; }&nbsp; &nbsp; newResourceWriter.Close();&nbsp; &nbsp; var newResource = new EmbeddedResource(dllResource.Name, dllResource.Attributes, newResourceOutputStream.ToArray());&nbsp; &nbsp; module.Resources.Remove(dllResource);&nbsp; &nbsp; module.Resources.Add(newResource);&nbsp; &nbsp; var woutput = new MemoryStream();&nbsp; &nbsp; asm.Write(woutput);&nbsp; &nbsp; var doutput = woutput.ToArray();&nbsp; &nbsp; Assembly assembly = Assembly.Load(doutput);}public static MemoryStream BitmapToByte(BitmapSource bitmapSource){&nbsp; &nbsp; var encoder = new System.Windows.Media.Imaging.PngBitmapEncoder();&nbsp; &nbsp; var frame = System.Windows.Media.Imaging.BitmapFrame.Create(bitmapSource);&nbsp; &nbsp; encoder.Frames.Add(frame);&nbsp; &nbsp; var stream = new MemoryStream();&nbsp; &nbsp; encoder.Save(stream);&nbsp; &nbsp; return stream;}public static void AttachAssembly(string myAsmFileName){&nbsp; &nbsp; Assembly assembly = Assembly.LoadFile(AppDomain.CurrentDomain.BaseDirectory + myAsmFileName); // LoadFrom&nbsp; &nbsp; AppDomain.CurrentDomain.Load(assembly.GetName());}重要提示:在遍历资源时,它们会变为小写,因此您必须使用小写的文件和文件夹名称。

精慕HU

您是否尝试过创建一个Bitmap然后将其设置为图像source?我认为这应该很容易。给你的图像一个名字,比如说theImage。你不可能不给它一个名字就引用这个图像。尝试以下操作:string path="/Pics/Image3.png";//path to the imagevar bitmapImage=new Bitmap(new Uri(path));theImage.source=bitmapImage;//set the bitmap as the source.不过,还有其他方法可以实现这一目标。希望这可以帮助?
打开App,查看更多内容
随时随地看视频慕课网APP