UWP缩略图与图像绑定x:bind

时间:2017-05-18 19:04:47

标签: c# xaml gridview mvvm binding

我试图通过x:Bind的数据模板将我的视频StorageFile的缩略图绑定到Image XAML元素。我正在使用MVVM方法,并且我已经使用相同的方法来实现这一点,但我不知道为什么它现在不起作用。

我使用实时属性资源管理器,Image的源代码为0.其他属性(如视频标题)工作正常,但图像无效。但问题是即使持续时间也会出现,有时持续时间会显示出来,有时也会出现问题,这很奇怪:/

我在下面提供我的代码。 感谢提前

模型

public class VideoItem : LibraryItem
{
    #region Props
    public string Views { get; set; }
    public string Duration { get; set; }
    public BitmapImage Display { get; set; }
    public VideoProperties MyVideoProperties { get; set; }
    public StorageFile MyVideoFile { get; set; }
    #endregion

    public VideoItem(StorageFile File)
    {
        MyVideoFile = File;
        Initialize();
    }

    #region PrivateMethods
    private async void Initialize()
    {
        Title = MyVideoFile.DisplayName;
        MyVideoProperties = await MyVideoFile.Properties.GetVideoPropertiesAsync();
        var dur = MyVideoProperties.Duration;
        Duration = $"{dur.Hours.ToString()} : {dur.Minutes.ToString()} : {dur.Seconds.ToString()}";
        Display = await GetDisplay();
        Views = MyVideoProperties.Rating.ToString();
    }

    private async Task<BitmapImage> GetDisplay()
    {
        var bitm = new BitmapImage();
        using (var imgSource = await MyVideoFile.GetScaledImageAsThumbnailAsync(ThumbnailMode.VideosView))
        {
            if (imgSource != null) { bitm.SetSource(imgSource); }
            else
            {
                var storelogoFolder = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFolderAsync("Assets");
                var storageLogoFile = await storelogoFolder.GetFileAsync("StoreLogo.png");
                bitm.UriSource = new Uri(storageLogoFile.Path);
            }
        }
        return bitm;
    }
    #endregion

}

 public class LibraryItem
{
    public string Title { get; set; }
}

视图模型

public class VideoLibraryViewModel
{
    #region Constructor
    public VideoLibraryViewModel(StorageFolder mainFolder)
    {

        VideoItems = new ObservableCollection<VideoItem>();
        MainFolder = mainFolder;
        Initialize();
    }
    #endregion

    #region Props
    public ObservableCollection<VideoItem> VideoItems { get; set; }
    #endregion


    #region PrivateFields
    private StorageFolder MainFolder;
    private IEnumerable<StorageFile> Videos;
    private char[] sep = new char[] { '/' };
    #endregion

    #region PrivateMethods
    private async void Initialize()
    {

        Videos = await MainFolder.GetFilesAsync();
        Videos = Videos.Where(a => a.ContentType.Split(sep)[0] == "video");
        FillUp();
    }

    private void FillUp()
    {

        foreach (var file in Videos)
        {
            VideoItems.Add(new VideoItem(file));
        }
    }
    #endregion


}

查看

<controls:AdaptiveGridView Name="VideosLibraryGridView" Grid.Row="1"
                           Header="Videos"
                           Style="{StaticResource MainGridView}"
                           ItemClick="VideosLibraryGridView_ItemClicked"
                           ItemsSource="{x:Bind VideoLibraryVM.VideoItems, Mode=OneWay}">
        <controls:AdaptiveGridView.ItemTemplate>
            <DataTemplate  x:DataType="data:VideoItem">
                <StackPanel Margin="4" >
                    <Grid>
                        <Image  Source="{x:Bind Display, Mode=OneWay}" Style="{StaticResource GridViewImage}"/>
                        <Border Style="{StaticResource TimeBorder}">
                            <TextBlock Text="{x:Bind Duration, Mode=OneWay}" Foreground="White"/>
                        </Border>
                    </Grid>
                    <TextBlock Text="{x:Bind Title,Mode=OneWay}"  Style="{StaticResource GridViewVideoName}"/>
                    <StackPanel Orientation="Horizontal" HorizontalAlignment="Stretch">
                        <TextBlock Text="{x:Bind Views,Mode=OneWay}" Style="{StaticResource GridViewViews}"/>
                        <TextBlock Text="Views" HorizontalAlignment="Right"/>
                    </StackPanel>
                </StackPanel>
            </DataTemplate>
        </controls:AdaptiveGridView.ItemTemplate>
    </controls:AdaptiveGridView>

图片样式

 <Style TargetType="Image" x:Key="GridViewImage">
    <Setter Property="Stretch" Value="UniformToFill"/>
    <Setter Property="HorizontalAlignment" Value="Center"/>
    <Setter Property="VerticalAlignment" Value="Center"/>
</Style>

在应用中输出,您可以看到gridview项目显示没有图像,没有持续时间,有时持续时间显示和图像永远不会显示

  

为什么没有形象?

     

为什么没有持续时间?

enter image description here

更新

我已经检查过断点,项目的所有属性都显示为空,除了标题之外,所有属性除了标题都是异步检索的,也许这就是原因?

1 个答案:

答案 0 :(得分:0)

  

项目的所有属性都显示为空,除了标题,所有与标题无关的属性都是异步检索的

这是因为UI只是渲染具有所有可用属性的网格项目,而没有等待异步方法的任何结果,因此为什么有时您会显示一些带有正确的loaded文本的项目,而有时却没有。

因此,逻辑解决方案是在gridview加载这些项目后后运行异步方法,对吧?

但是如何?将其放在datatemplate内的ContainerContentChanging事件下不会改变任何内容,因为它只会再次发生相同的问题。

好吧,由于该事件本身的工作原理,您可以通过滥用Gridview控件中的<controls:AdaptiveGridView Name="VideosLibraryGridView" Grid.Row="1 ContainerContentChanging="VideosLibraryGridView_ContainerContentChanging" Header="Videos" Style="{StaticResource MainGridView}" ItemClick="VideosLibraryGridView_ItemClicked" ItemsSource="{x:Bind VideoLibraryVM.VideoItems, Mode=OneWay}"> <!--something something--> </controls:AdaptiveGridView> 事件来实现此目的。

Page.xaml

private void VideosLibraryGridView_ContainerContentChanging(ListViewBase sender, ContainerContentChangingEventArgs args
{
    args.RegisterUpdateCallback(LoadImage);
}

private async void LoadImage(ListViewBase sender, ContainerContentChangingEventArgs args)
{
    var templateRoot = args.ItemContainer.ContentTemplateRoot as Grid;
    var imageurl = (args.Item as model).ThumbnailUri;
    var cache = await getimagefromfileasync(imageurl);
    //check your image location based on your template first.
    var image = templateRoot.Children[0] as Image; 
    image.Source = new BitmapImage()
    {
        UriSource = new Uri(cache.Path)
    };
    image.Opacity = 1;
}

Page.xaml.cs

{{1}}

上面的代码是我为了异步加载缓存的缩略图所做的。

来源:

  1. Dramatically Increase Performance when Users Interact with Large Amounts of Data in GridView and ListView
  2. ContainerContentChanging Event
  3. Update ListView and GridView items progressively