【问题标题】:Specified cast not Valid when updating Item in ObservableCollection bound to Listview更新绑定到 Listview 的 ObservableCollection 中的项目时,指定的强制转换无效
【发布时间】:2018-10-13 17:37:14
【问题描述】:

我正在尝试使用https://github.com/jamesmontemagno/MediaPlugin 将设备中的图像添加到我在 Xamarin 中的应用程序。奇怪的是,添加 Item 会在“两行之间”的某个点引发异常。我不知道如何调试它并假设它发生在实现 OnPropertyChanged 错误。

我将异常包装在 Try/Catch 块中,令我惊讶的是,该项目实际上已添加,App.api.message.MediaFiles.Count() 已增加。这使我假设 Exeption 实际上在 .Add(Item) 之后发生但不是在 .Add(Item) 之后发生。

这必须是OnPropertyChanged()(但是为什么调试器没有向我显示那部分代码?)或者是 Xamarin 将 Listview 绑定到 ...Thumbnail 的幕后魔法。

但是,由于这两个选项对我来说都是相对较新的选项,因此这里很可能会出现错误或误解,任何有关如何或在何处进行调查的提示将不胜感激。

以下是我的详细操作:

 [...]
    public MainPage()
    {
        InitializeComponent();
        BindingContext = App.api.message;
        Media.ItemsSource = App.api.message.MediaFiles;
      [...]
    }

XAML 中的列表视图:

[...]
<ListView x:Name="Media" BackgroundColor="#f1f1f1" HasUnevenRows="true" IsVisible="true" Header="Media" ItemTapped="RemoveImage" RowHeight="90" HeightRequest="120">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <Image Source="{Binding thumbnail}" />
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView> 
[...]

file 来自我挑选或拍摄图像:

    public void AddFile(MediaFile file)
    { 
        Classes.MessageClass.Media Item = new Classes.MessageClass.Media();

        Item.Filename = file.Path;

        Item.Thumbnail = ImageSource.FromStream(() =>
        {
            var stream = file.GetStreamWithImageRotatedForExternalStorage();
            return stream;
        });

        file.Dispose();

        FileInfo fileInfo = new FileInfo(Item.Filename);
        Item.Size = fileInfo.Length;

        Console.WriteLine("\n\nOriginal File:{0} \n{1:###,###,###} Bytes\nCaption: {2}\nContent Type: {3}", Item.Filename, Item.Size, Item.Caption,Item.ContentType);

        try
        {
            App.api.message.MediaFiles.Add(Item);  //EXEPTION "Specified cast not Valid"
        }
        catch (Exception ex)
        {
            Console.WriteLine("Exeption: " + ex.Message + " " + ex.Data.Values.ToString());
        }
        Console.WriteLine("Attached Images: " + App.api.message.MediaFiles.Count());
        App.api.message.HasMedia = true;

        UpdateImagesUI();
    }

最后是我对Classes.MessageClass.Media 的定义。 (我添加了值来排除空值问题):

public class Media
    {
        public string Caption { get; set; } = "";
        public string Filename { get; set; } = "";
        ImageSource thumbnail;
        public long Size { get; set; } = 0;
        public string ContentType { get; set; } = "";
        public bool IsVideo { get; set; } = false;
        public ImageSource Thumbnail
        {
            get
            { 
                return thumbnail;
            }
            set 
            { 
                if ((thumbnail != value) && (value != null))
                {
                    thumbnail = value;
                    Console.WriteLine("Image Updated");
                    OnPropertyChanged("Thumbnail");
                }
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(string propertyName)
        {
            var changed = PropertyChanged;
            if (changed != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }

还有in MessageClass()MediaFiles = new ObservableCollection&lt;Media&gt;();

最后是堆栈:

 (System.Collections.Specialized.NotifyCollectionChangedEventArgs e) [0x0000f] in /Library/Frameworks/Xamarin.iOS.framework/Versions/12.0.0.15/src/Xamarin.iOS/mcs/class/referencesource/System/compmod/system/collections/objectmodel/observablecollection.cs:288 
 at  System.Collections.ObjectModel.ObservableCollection`1[T].OnCollectionChanged (System.Collections.Specialized.NotifyCollectionChangedAction action, System.Object item, System.Int32 index) [0x00000] in /Library/Frameworks/Xamarin.iOS.framework/Versions/12.0.0.15/src/Xamarin.iOS/mcs/class/referencesource/System/compmod/system/collections/objectmodel/observablecollection.cs:351 
 at System.Collections.ObjectModel.ObservableCollection`1[T].InsertItem (System.Int32 index, T item) [0x00024] in /Library/Frameworks/Xamarin.iOS.framework/Versions/12.0.0.15/src/Xamarin.iOS/mcs/class/referencesource/System/compmod/system/collections/objectmodel/observablecollection.cs:219 
 at System.Collections.ObjectModel.Collection`1[T].Add (T item) [0x00020] in /Library/Frameworks/Xamarin.iOS.framework/Versions/12.0.0.15/src/Xamarin.iOS/mcs/class/referencesource/mscorlib/system/collections/objectmodel/collection.cs:67 
 at SegelnBlogsEditor.MainPage.AddFile (Plugin.Media.Abstractions.MediaFile file) [0x0009e] in /Users/hinnerkweiler/wwwroot/SegelnBlogsEditor/SegelnBlogsEditor/MainPage.xaml.cs:292

【问题讨论】:

  • 堆栈跟踪显示什么?
  • 感谢您查看此@Jason。我将跟踪附加到上面的帖子。不太确定可以从中学到什么;)

标签: c# xamarin xamarin.forms plugin.media.crossmedia


【解决方案1】:

ImageSource.FromStream 方法将 Action 作为参数,每次需要渲染 ViewCell 时都会对其进行评估。在操作中使用 file 引用以供以后使用并处理它会导致异常。

编辑:

更好的方法是从文件名获取图像

Image.Thumbnail = ImageSource.FromFile(Item.Filename);

【讨论】:

  • 只是为了澄清。这是否意味着在 Item.Thumbnail = ImageSource.FromStream(() ... 中我不是将 stream 内容返回到属性,而是返回 Action 本身?
  • ImagSource.FromStream 评估 Action 并返回流。但是file 对象已经被释放了,如果它抛出异常,请检查MediaPlugin Source
  • 好的,我明白了。实际上,我转向Image.Thumbnail = ImageSource.FromFile(Item.Filename);- 最初是为了解决这个问题,因为那样我就有可能将一堆 50MB 的图像显示为缩略图。非常感谢您指出我进一步阅读。
  • 另外,我建议你看看FFImageLoading library
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-22
  • 2018-05-27
  • 2014-07-30
  • 2012-06-12
  • 1970-01-01
相关资源
最近更新 更多