欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

如何在双向绑定的Image控件上绘制自定义标记(wpf)

程序员文章站 2022-06-13 08:09:48
我们的需求是什么? 答:需要在图片上增加一些自定义标记,例如:2个图片对比时,对相同区域进行高亮。 先上效果图: 设计思路 1.概述 1.通过TargeUpdated事件,重新绘制图片进行替换。 2.详细实现 1.我们先绑定ImageTargetUpdated事件。 根据微软官方文档,如上图,我们需 ......

我们的需求是什么?

答:需要在图片上增加一些自定义标记,例如:2个图片对比时,对相同区域进行高亮。

先上效果图:

如何在双向绑定的Image控件上绘制自定义标记(wpf)

 

 

 

设计思路

1.概述

1.通过targeupdated事件,重新绘制图片进行替换。

2.详细实现

1.我们先绑定imagetargetupdated事件。

<image x:name="destimagecontrol" source="{binding path=source.url, notifyontargetupdated=true}" targetupdated="imagetargetupdated">

根据微软官方文档,如上图,我们需要设置notifyonrargetupdated的值,官方文档如下:

如何在双向绑定的Image控件上绘制自定义标记(wpf)

 

 

 2.在响应方法中,对图像进行绘制。

private void imagetargetupdated(object sender, datatransfereventargs e)
{
    //todo:绘制图像:drawingimage = drawimage......
    //设置新图像:destimagecontrol.setcurrentvalue(image.sourceproperty, drawingimage);
}

 

3.按照上面的思路,很完美,于是我们遇到了问题

什么?有什么问题?在直接读取image控件的source时,我们发现它是没有值的,所以我们绘制的图片底图是没有的。

下面我们来分析一下:

由于image控件的source我们是绑定的url(类似:http://xxx.xxx.com/xxx.jpg),所以wpf会进行一步下载,通过调试,我们会发现它此时的类是lateboundbitmapdecoder。

关于类lateboundbitmapdecoder的官方文档如下:

如何在双向绑定的Image控件上绘制自定义标记(wpf)

 

 

 

我们发现,这个类加载图片是异步的。所以我们在targeupdated事件中直接拿到的source,此时仅仅是一个空对象,他的数据还在网络中传输。知道原理就好办了。

我们对source绑定下载完成事件!

if (((bitmapframe)imagecontrol.source).isdownloading)
{
    //如果是异步下载,则绑定下载完成后事件
    ((bitmapframe)imagecontrol.source).decoder.downloadcompleted += (sender2, e2) =>
    {
        bitmapsource sourceimg = (bitmapsource)((lateboundbitmapdecoder)sender2).frames[0];
        drawimage(sourceimg);
    };
}
else
{
    //如果已存在图片,则直接使用
    bitmapsource sourceimg = (bitmapsource)imagecontrol.source;
    drawimage(sourceimg);
}

 

再试运行一下,就和最前面的效果图一致了。

总结

1.对于双向绑定的image控件,我们在原图上增加内容时,可以响应targeupdated事件进行自定义绘制。

2.在targeupdated事件响应中,有可能拿不到source,此时,我们需要绑定下载完成事件,在事件中进行底图的获取。

3.我们需要使用setcurrentvalue方法对source进行赋值,如此不会影响双向绑定。

 

ps:

1.此文仅介绍遇到问题的解决思路及解决过程,并不分享源码。