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

Posted lonelyxmas

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在双向绑定的Image控件上绘制自定义标记(wpf)相关的知识,希望对你有一定的参考价值。

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

我们的需求是什么?

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

先上效果图:

技术图片

 

 

 

设计思路

1.概述

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

2.详细实现

1.我们先绑定ImageTargetUpdated事件。

1
<Image x:Name="DestImageControl" Source="{Binding Path=Source.Url, NotifyOnTargetUpdated=True}" TargetUpdated="ImageTargetUpdated">

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

技术图片

 

 

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

1
2
3
4
5
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的官方文档如下:

技术图片

 

 

 

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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.此文仅介绍遇到问题的解决思路及解决过程,并不分享源码。

 

以上是关于如何在双向绑定的Image控件上绘制自定义标记(wpf)的主要内容,如果未能解决你的问题,请参考以下文章

vue表单控件绑定+自定义组件

如何创建从 vue.js 实例到自定义原生 Web 组件的双向绑定?

vue 自定义组件使用v-model

WPF Image控件如何根据数据状态绑定不同的图片

C# wpf 如何实现自定义控件,布局时,大小发生变化,内部绘制的曲线跟随变化?

我的控件的双向数据绑定