我們的需求是什么?
答:需要在圖片上增加一些自定義標記,例如: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.此文僅介紹遇到問題的解決思路及解決程序,并不分享原始碼,
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/22568.html
標籤:WPF
上一篇:wpf 兩個自定義控制元件
