如何在雙向綁定的Image控件上繪制自定義標記(wpf)


我們的需求是什么?

答:需要在圖片上增加一些自定義標記,例如:2個圖片對比時,對相同區域進行高亮。

先上效果圖:

 

 

 

設計思路

1.概述

1.通過TargeUpdated事件,重新繪制圖片進行替換。

2.詳細實現

1.我們先綁定ImageTargetUpdated事件。

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

根據微軟官方文檔,如上圖,我們需要設置NotifyOnRargetUpdated的值,官方文檔如下:

 

 

 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的官方文檔如下:

 

 

 

我們發現,這個類加載圖片是異步的。所以我們在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.此文僅介紹遇到問題的解決思路及解決過程,並不分享源碼。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM