为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

C#
慕沐林林 2022-06-18 16:21:04
在我的 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 回答

?
DIEA

TA贡献1820条经验 获得超3个赞

花了几天时间,但我想出了一个解决方案!


我将所有图像移动到同一解决方案中的另一个 C# 项目中,设置为编译为名为 DynamicResources.dll 的类库 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());

}

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


查看完整回答
反对 回复 2022-06-18
?
精慕HU

TA贡献1845条经验 获得超8个赞

您是否尝试过创建一个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.

不过,还有其他方法可以实现这一目标。希望这可以帮助?


查看完整回答
反对 回复 2022-06-18
  • 2 回答
  • 0 关注
  • 196 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号