通过将Image.Source设置为null的绑定来引发绑定错误的解决方案。 (抑制?)

时间:2011-02-14 21:16:47

标签: c# .net wpf binding

我有一个场景,我将Image Sources设置为null,稍后解析然后显示。有什么好办法阻止我的代码抛出绑定错误?

一个例子:

  

System.Windows.Data错误:23:无法将''从类型''转换为'en-US'文化的'System.Windows.Media.ImageSource',默认转换为;考虑使用Binding的Converter属性。 NotSupportedException:'System.NotSupportedException:ImageSourceConverter无法转换(null)。      at System.ComponentModel.TypeConverter.GetConvertFromException(Object value)      在System.Windows.Media.ImageSourceConverter.ConvertFrom(ITypeDescriptorContext context,CultureInfo culture,Object value)      在MS.Internal.Data.DefaultValueConverter.ConvertHelper(Object o,Type destinationType,DependencyObject targetElement,CultureInfo culture,Boolean isForward)'

XAML

<Image x:Name="image" Height="Auto" Width="Auto" Opacity="0">
    <Image.Effect>
        <DropShadowEffect/>
    </Image.Effect>
    <Image.Source>
        <Binding Path="ImageStream">
            <Binding.ValidationRules>
                <validationRules:NotNullStreamValidationRule/>
            </Binding.ValidationRules>
        </Binding>
    </Image.Source>
</Image>

C#

namespace FlickrDemo.ViewModel
{
    public class FlickrPhotoViewModel : ViewModelBase
    {
        public const string ImageStreamPropertyName = "ImageStream";

        private Stream _imageStream = null;

        public Stream ImageStream
        {
            get
            {
                return _imageStream;
            }

            set
            {
                if (_imageStream == value)
                {
                    return;
                }
                _imageStream = value;

                RaisePropertyChanged(ImageStreamPropertyName);
            }
        }

        public const string IsLoadingPropertyName = "IsLoading";

        private bool _isLoading = false;

        public bool IsLoading
        {
            get
            {
                return _isLoading;
            }

            set
            {
                if (_isLoading == value)
                {
                    return;
                }

                _isLoading = value;

                RaisePropertyChanged(IsLoadingPropertyName);
            }
        }

        public const string PhotoIDPropertyName = "PhotoID";

        private string _photoID = String.Empty;

        public string PhotoID
        {
            get
            {
                return _photoID;
            }

            set
            {
                if (_photoID == value)
                {
                    return;
                }

                var oldValue = _photoID;
                _photoID = value;

                RaisePropertyChanged(PhotoIDPropertyName);
            }
        }

        public FlickrPhotoViewModel(string photoID)
        {
            this.PropertyChanged += async (s, e) =>
            {
                if (e.PropertyName == ImageStreamPropertyName)
                {
                    if (!(ImageStream == null || ImageStream == Stream.Null))
                    {
                        IsLoading = false;
                    }
                }
            };
            IsLoading = true;
            PhotoID = photoID;
        }
    }
}

3 个答案:

答案 0 :(得分:2)

我遇到了同样的问题,试图使用字符串URI(而不是Stream)。我通过在ImageSource类型的视图模型上设置属性来解决此问题,ImageSource是Image上的Source属性的类型,并将Source绑定到该属性。这可以从混合中获得任何自动转换。在新属性中,处理null case,然后遵循标准ImageSourceConverter。在你的情况下,我认为这看起来像这样:

代码:

public const string ImageStreamPropertyName = "ImageStream";

private Stream _imageStream = null;

public Stream ImageStream
{
    get
    {
        return _imageStream;
    }

    set
    {
        if (_imageStream == value)
        {
            return;
        }
        _imageStream = value;

        RaisePropertyChanged(ImageStreamPropertyName);
        // Raise for ImageSource too since it changes with ImageStream
        RaisePropertyChanged("ImageSource");
    }
}

public ImageSource ImageSource
{
    get
    {
        if (ImageStream == null)
            return null;

        return (ImageSource)new ImageSourceConverter().ConvertFrom(ImageStream);
    }
}

XAML:

    <Image.Source>
        <Binding Path="ImageSource" />
    </Image.Source>

答案 1 :(得分:1)

问题是ImageStream属性的数据类型。没有转换器知道如何处理null情况:

System.Windows.Data错误:23:无法将''从类型''转换为'en-US'文化的'System.Windows.Media.ImageSource',默认转换为; 考虑使用Binding的Converter属性

解决此问题的一种可能性是实现自己的IValueConverter实施。如果输入值是流,则返回它。如果不是,则返回null。如果这不起作用,请返回一个空的假人ImageSource

类似的东西:

public class ImageStreamForwardConverter : IValueConverter{
    public object Convert(object value, Type targetType, object parameter, CultureInfo    culture){
      if(null == value){
         return null;
      }else if(value is Stream){
         return value;
      }else{
         throw new InvalidOperationException("Unsupported type");
      }
      ....

答案 2 :(得分:0)

Pat在以下链接中的回答对我来说很有用,它涉及一个简单的值转换器,在null的情况下返回DependencyProperty.UnsetValue。

ImageSourceConverter error for Source=null