Xamarin:UITableView单元格图像在从网络获取时直到单击单元格时才显示在单元格中

时间:2015-01-05 21:30:24

标签: ios uitableview xamarin

我想在cell.ImageView.Image控制器的UITableView方法中将网址中的图片显示为GetCell变量。出于某种原因,仅当我单击单元格时才会显示图像。它正在获取图像,但是单元格没有被更新。数据是ObservableCollection,所以我不确定我缺少什么。我是否需要明确调用任何方法?

public class PasswordGroupsDataSource : UITableViewDataSource
{
    const string PlaceholderImagePath = "Placeholder.jpg";
    UIImage PlaceholderImage { get; set; }
    PasswordsViewController Controller { get; set; }
    List<Password> Apps;
    public ObservableCollection<PasswordGroup> Groups { get; set; }
    public PasswordGroupsDataSource(ObservableCollection<PasswordGroup> groups, PasswordsViewController controller, List<Password> passwords)
    {
        Controller = controller;
        Apps = passwords;
        PlaceholderImage = UIImage.FromFile("Images/Placeholder.png");

        if (groups == null)
        {
            throw new ArgumentNullException("groups");
        }
        Groups = groups;
        groups.CollectionChanged += HandleAppsCollectionChanged;

        // If either a download fails or the image we download is corrupt, ignore the problem.
        TaskScheduler.UnobservedTaskException += delegate(object sender, UnobservedTaskExceptionEventArgs e)
        {
            e.SetObserved();
        };
    }
    void HandleAppsCollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        // Whenever the Items change, reload the data.
        Controller.TableView.ReloadData();
    }

    public Password GetPerson(NSIndexPath indexPath)
    {
        try
        {
            var personGroup = Groups[indexPath.Section];
            return personGroup.People[indexPath.Row];
        }
        catch (Exception exc)
        {
            Console.WriteLine("Error in GetPerson: " + exc.Message);

            //Occasionally we get an index out of range here
            return null;
        }
    }

    public override string TitleForHeader(UITableView tableView, nint section)
    {
        return Groups[(int)section].Title;
    }

    public override string[] SectionIndexTitles(UITableView tableView)
    {
        return Groups.Select(x => x.Title).ToArray();
    }

    public override nint NumberOfSections(UITableView tableView)
    {
        return Groups.Count;
    }

    public override nint RowsInSection(UITableView tableView, nint section)
    {
        return Groups[(int)section].People.Count;
    }

    public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
    {
        var cell = tableView.DequeueReusableCell("P") as PasswordCell;
        if (cell == null)
        {
            cell = new PasswordCell("P");
        }

        var person = GetPerson(indexPath);
        cell.Tag = indexPath.Row;
        if (person != null)
        {
            cell.Person = person;

            if (person.Image == null)
            {
                person.Image = PlaceholderImage;
                BeginDownloadingImage(person, indexPath);
            }
            cell.ImageView.Image = person.Image;
        }

        return cell;
    }

    #region Image Support

    readonly Dictionary<string, UIImage> images = new Dictionary<string, UIImage>();
    readonly List<string> imageDownloadsInProgress = new List<string>();
    readonly ImageDownloader imageDownloader = new UIKitImageDownloader();

    async void BeginDownloadingImage(Password app, NSIndexPath path)
    {
        // Queue the image to be downloaded. This task will execute
        // as soon as the existing ones have finished.
        byte[] data = null;

        data = await GetImageData(app.GravatarUrl.ToString());
        app.Image = UIImage.LoadFromData(NSData.FromArray(data));

        InvokeOnMainThread(() =>
        {
            if (Apps != null)
            {
                var cell = Controller.TableView.VisibleCells.Where(c => c.Tag == Apps.IndexOf(app)).FirstOrDefault();
                if (cell != null)
                    cell.ImageView.Image = app.Image;
            }
        });
    }

    async Task<byte[]> GetImageData(string ImageUrl)
    {
        byte[] data = null;
        try
        {
            UIApplication.SharedApplication.NetworkActivityIndicatorVisible = true;
            using (var c = new GzipWebClient())
                data = await c.DownloadDataTaskAsync(ImageUrl);
        }
        finally
        {
            UIApplication.SharedApplication.NetworkActivityIndicatorVisible = false;
        }

        return data;
    }
    public override bool CanEditRow(UITableView tableView, NSIndexPath indexPath)
    {
        return true;
    }
    public override void CommitEditingStyle(UITableView tableView, UITableViewCellEditingStyle editingStyle, NSIndexPath indexPath)
    {
        if (editingStyle == UITableViewCellEditingStyle.Delete)
        {
            Groups.RemoveAt(indexPath.Row);
        }
    }

    #endregion
}

当我调试它时,我可以看到图像是在BeginDownloadingImage函数中设置的。我错过了什么?为什么在单击单元格之前单元格没有更新?

注意:我使用的是Xamarin员工目录样本。

1 个答案:

答案 0 :(得分:0)

我不确定你能这样做。我会覆盖Person对象上的占位符Image,然后从tableview中调用ReloadRows。

InvokeOnMainThread(() =>
            {
                if (Apps != null)
                {
                    person.Image = app.Image;
                    Controller.TableView.ReloadRows (new NSIndexPath[]{ path }, UITableViewRowAnimation.Fade);
                }
            });