UWP GridView数据绑定不使用异步方法(可观察集合)

时间:2015-11-03 14:31:28

标签: gridview observablecollection datatemplate uwp

好的我会尝试一步一步地解释我的问题以及代码

  1. 我第一次尝试使用x:bind和observable colection的数据模板
  2. 当我尝试获取一组存储文件的缩略图并将其与显示名称一起显示时,它不起作用。
  3. 当我只是简单地将新项目添加到我的可观察集合中时,这些文件的名称没有获取缩略图并且放置一个简单的图片而不是来自资产的缩略图,那么它就像它应该的那样工作,但我得到资产pic而不是我的缩略图。请帮忙,下面是我的代码生病评论它解释得更好。提前谢谢..

    //this is the xaml code of the gridview.
    <GridView ItemsSource="{x:Bind VideoGridItems}">
        <GridView.ItemTemplate>
            <DataTemplate x:DataType="data:VideoGridItem">
                <StackPanel>
                    <Image Source="{x:Bind i}" Width="190" Height="130"/>
                    <TextBlock Text="{x:Bind Name}" FontSize="24"/>
                </StackPanel>
            </DataTemplate>
        </GridView.ItemTemplate>
    </GridView>
    

    //这是我在xaml.cs文件背后的全部代码

    public sealed partial class HistoryV : Page
    {
    public HistoryV()
    {
        this.InitializeComponent();
        VideoGridItems = new ObservableCollection<VideoGridItem>();
        LoadHistory();
    }
    
    
    
    public ObservableCollection<VideoGridItem> VideoGridItems { get; set; }
    private async void LoadHistory()
    {
        var files = new List<StorageFile>();
        var TextFile = await Current.LocalFolder.CreateFileAsync("VideoHistory.txt", CreationCollisionOption.OpenIfExists);
        var Lines = await FileIO.ReadLinesAsync(TextFile);
        int i = Lines.Count - 1;
        for (; i>-1; i--)
        {
            files.Add(await StorageApplicationPermissions.FutureAccessList.GetFileAsync(Lines[i]));
        }
         //I simply take each file and add new items with its name and
         asset picture as image on gridview, this method works, but not what I want
        foreach (var item in files)
        {
            VideoGridItems.Add(new VideoGridItem { Name = item.DisplayName, i = new BitmapImage(new Uri("ms-appx:///Assets//StoreLogo.png")) });
        }
         //below the is code line i have commented because it is not working
         this is the actual method which should work.
        //VideoGridItems = await GetVideoItems(files);
    }
    

    }

  4. 下面是我用GetVideoItems方法创建的两个类,以便获得可以绑定到gridview的ObservableCollection

       public class VideoGridItem
    {
        public BitmapImage i { get; set; }
        public string Name { get; set; }
    }
    class VideoGridItemManager
    {
        public static async Task<ObservableCollection<VideoGridItem>> GetVideoItems(List<StorageFile> files)
        {
            var newlist = new ObservableCollection<VideoGridItem>();
            foreach (var file in files)
            {
                var b = new BitmapImage();
                var thumb =await  GetThumbnail(file);
                if (thumb == null) { b = new BitmapImage(new Uri("ms-appx:///Assets//Square150x150Logo.scale-200.png")); }
                else
                {
                    if (thumb.ContentType == "image/bmp")
                    {
                        b = new BitmapImage(new Uri("ms-appx:///Assets//Square150x150Logo.scale-200.png"));
                    }
                    else
                    {
                        await b.SetSourceAsync(thumb);
                    }
                }
                newlist.Add(new VideoGridItem { Name = file.DisplayName, i=b });
            }
            return newlist;
        }
        private static async Task<StorageItemThumbnail> GetThumbnail(StorageFile file)
        {
            var thumb = await file.GetThumbnailAsync(ThumbnailMode.VideosView, 190, ThumbnailOptions.UseCurrentScale);
            return thumb;
        }
    }
    

1 个答案:

答案 0 :(得分:3)

x:bind的数据模板是正确的,可以使用异步方法。这里的问题与ObservableCollection有关。在您的代码中,您使用VideoGridItems = await GetVideoItems(files);更新了GridView,但替换此类ObservableCollection不会引发任何通知,GridView仍然绑定旧版本。解决此问题的一种简单方法是使用Add方法通知更改,如下所示:

VideoGridItems.Clear();
foreach (var item in await VideoGridItemManager.GetVideoItems(files))
{
    VideoGridItems.Add(item);
}

我使用KnownFolders.PicturesLibrary作为我身边的一个简单测试:

private async void LoadHistory()
{
    var files = await KnownFolders.PicturesLibrary.GetFilesAsync();

    VideoGridItems.Clear();
    foreach (var item in await VideoGridItemManager.GetVideoItems(files))
    {
        VideoGridItems.Add(item);
    }
}

效果很好。

<强> [更新]

使用绑定时,如果您希望在数据源更改后更新UI,则需要引发PropertyChanged事件。如果将全新的可观察集合分配给现有集合,则不会引发任何PropertyChanged事件,因此您的GridView将不会更新。但是,如果您使用“添加”方法,则会引发PropertyChanged事件。您可以在ObservableCollection的{​​{3}}中找到这个。

    protected override void InsertItem(int index, T item)
    {
        CheckReentrancy();
        base.InsertItem(index, item);

        OnPropertyChanged(CountString);
        OnPropertyChanged(IndexerName);
        OnCollectionChanged(NotifyCollectionChangedAction.Add, item, index);
    } 

如果您希望在将全新的可观察集合分配给VideoGridItems后进行UI更新,则可以触发PropertyChanged事件以通知视图集合已被替换。

public sealed partial class MainPage : Page, INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private ObservableCollection<VideoGridItem> _videoGridItems;

    public ObservableCollection<VideoGridItem> VideoGridItems
    {
        get
        {
            return _videoGridItems;
        }

        set
        {
            _videoGridItems = value;
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs("VideoGridItems"));
            }
        }
    }

    public MainPage()
    {
        this.InitializeComponent();
        VideoGridItems = new ObservableCollection<VideoGridItem>();
        LoadHistory();
    }
    ...
}

在您的XAML中,您需要使用ItemsSource="{x:Bind VideoGridItems, Mode=OneWay}",因为@gregkalapos说。