如果ImageSource引用一个不可达到的URL,我该如何保持WPF图像不被阻止? [英] How can I keep a WPF Image from blocking if the ImageSource references an unreachable Url?

查看:193
本文介绍了如果ImageSource引用一个不可达到的URL,我该如何保持WPF图像不被阻止?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个WPF应用程序,并尝试使用以下XAML将图像绑定到视图模型:

  ; Image Source ={Binding Author.IconUrl,IsAsync = True}/> 

问题是图像URL是由用户定义的,通常可以参考内联网上托管的图像服务器。当WPF应用程序远程运行时,它会在尝试解决现在无法访问的映像时锁定。



我以为IsAsync绑定属性会导致在后台发生负载,但是看起来DNS主机上仍然可能发生DNS解析? p>

即使图像无法访问,我可以做些什么来保护我的应用程序?



谢谢
Corey

解决方案

这是一个新的答案,希望比我之前的更好。



当您使用IsAsync创建绑定为true时,它将在单独的线程上执行对Author.IconUrl的属性访问,但是在主线程中将Uri转换为ImageSource。正如您所发现的那样,转换将在主线程上进行DNS查找,导致应用程序锁定。



由于您的源代码是http / https,WPF将自动处理异步加载图像源。所以我怀疑你需要做的只是使DNS查找异步。



这可以通过使用附加的属性进行自动化:

 < Image my:ImageAsyncHelper.SourceUri ={Binding Author.IconUrl}/> 

其中ImageAsyncHelper定义为:

  public class ImageAsyncHelper:DependencyObject 
{
public static Uri GetSourceUri(DependencyObject obj){return(Uri)obj.GetValue(SourceUriProperty); }
public static void SetSourceUri(DependencyObject obj,Uri value){obj.SetValue(SourceUriProperty,value); }
public static readonly DependencyProperty SourceUriProperty = DependencyProperty.RegisterAttached(SourceUri,typeof(Uri),typeof(ImageAsyncHelper),new PropertyMetadata
{
PropertyChangedCallback =(obj,e)=>
{
((Image)obj).SetBinding(Image.SourceProperty,
new Binding(VerifiedUri)
{
Source = new ImageAsyncHelper {GivenUri = Uri)e.NewValue},
IsAsync = true,
});
}
});

Uri GivenUri;
public Uri VerifiedUri
{
get
{
try
{
Dns.GetHostEntry(GivenUri.DnsSafeHost);
return GivenUri;
}
catch(异常)
{
返回null;
}

}
}
}

它的工作原理是:


  1. 设置附加属性时,会创建一个ImageAsyncHelper的实例,并异步绑定图像。来源于ImageSource的async帮助器对象。

  2. 当异步绑定触发时,会调用VerifiedUri getter来验证地址是否可访问,然后返回GivenUri

  3. 如果您的IconUri属性发生更改,则绑定会导致附加属性更新,从而创建并绑定新的ImageAsyncHelper,以使图像保持最新。


I'm writing a WPF application and trying to bind an image to my view model with the following XAML:

<Image Source="{Binding Author.IconUrl, IsAsync=True}" />

The problem is that the image URLs are defined by users and can often refer to images hosted on intranet web servers. When the WPF application is run remotely, it locks up while trying to resolve the images that are now unreachable.

I thought the "IsAsync" binding property would cause the load to happen in the background, but it appears that the DNS resolution may still happen in the main thread?

What can I do to keep my app from locking, even if the images are unreachable?

Thanks, Corey

解决方案

Here is a new answer for you, hopefully better than my earlier one.

When you create your binding with 'IsAsync' true, it executes the property access to Author.IconUrl on a separate thread but does the conversion from Uri to ImageSource in the main thread. As you discovered, the conversion does a DNS lookup on the main thread causing the application to lock up.

Since your source is http/https, WPF will automatically handle asynchronously loading the image source. So I suspect all you need to do is to make just the DNS lookup asynchronous.

This can be automated by using an attached property:

<Image my:ImageAsyncHelper.SourceUri="{Binding Author.IconUrl}" />

where ImageAsyncHelper is defined as:

public class ImageAsyncHelper : DependencyObject
{
  public static Uri GetSourceUri(DependencyObject obj) { return (Uri)obj.GetValue(SourceUriProperty); }
  public static void SetSourceUri(DependencyObject obj, Uri value) { obj.SetValue(SourceUriProperty, value); }
  public static readonly DependencyProperty SourceUriProperty = DependencyProperty.RegisterAttached("SourceUri", typeof(Uri), typeof(ImageAsyncHelper), new PropertyMetadata
  {
    PropertyChangedCallback = (obj, e) =>
    {
      ((Image)obj).SetBinding(Image.SourceProperty,
        new Binding("VerifiedUri")
        {
          Source = new ImageAsyncHelper { GivenUri = (Uri)e.NewValue },
          IsAsync = true,
        });
    }
  });

  Uri GivenUri;
  public Uri VerifiedUri
  {
    get
    {
      try
      {
        Dns.GetHostEntry(GivenUri.DnsSafeHost);
        return GivenUri;
      }
      catch(Exception)
      {
        return null;
      }

    } 
  } 
}

The way this works is:

  1. When you set the attached property it creates an instance of an ImageAsyncHelper and asynchronously binds the Image.Source to the ImageSource propety of the async helper object.
  2. When the asynchronous binding fires it calls the VerifiedUri getter which verifies the address is accessible then returns the GivenUri
  3. If your IconUri property ever changes, the binding causes the attached property to update which creates and binds a new ImageAsyncHelper so the images stays up to date.

这篇关于如果ImageSource引用一个不可达到的URL,我该如何保持WPF图像不被阻止?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆