C# · 12月 23, 2021

c# – 如何在UWP MVVM模型中使我的构造函数异步? (MVVM Lighttoolkit)

我有一个想要读取StorageFolder VideosLibrary的UWP项目,并在带缩略图的Views中显示mp4文件列表.

使用MVVM ligth工具包,我已经使用xaml设置了这4只苍蝇.
Xaml正在使用UWP社区工具箱包装面板.

1)viewmodelLocator.cs

namespace UWP.viewmodels{/// <summary>/// This class contains static reference to all the view models in the /// application and provides an entry point for the bindings./// </summary>class viewmodelLocator{ /// <summary> /// Initializes a new instance of the viewmodelLocator class. /// </summary> public viewmodelLocator() { ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default); if (viewmodelBase.IsInDesignModeStatic) { // Create design time view services and models } else { // Create run Time view services and models } //Register services used here SimpleIoc.Default.Register<VideoListModel>(); } public VideoListModel VideoListModel { get { return ServiceLocator.Current.GetInstance<VideoListModel>(); }}}

2)VideoListItem.cs

namespace UWP.Models{class VideoListItem : viewmodelBase{ public string VideoName { get; set; } public string Author { get; set; } public Uri Vid_url { get; set; } public BitmapImage Image { get; set; } public VideoListItem(string videoname,string author,Uri url,BitmapImage img) { this.VideoName = videoname; this.Author = author; this.Vid_url = url; this.Image = img; }}}

3)VideoListModel.cs

namespace UWP.viewmodels{class VideoListModel : viewmodelBase{ public ObservableCollection<VideoListItem> VideoItems { get; set; } private VideoListItem videoItems; public VideoListModel() { } public async static Task<List<VideoListItem>> GetVideoItem() { List<VideoListItem> videoItems = new List<VideoListItem>(); StorageFolder videos_folder = await KNownFolders.VideosLibrary.CreateFolderAsync(“Videos”); var queryOptions = new QueryOptions(CommonFileQuery.DefaultQuery,new[] { “.mp4″ }); var videos = await videos_folder.CreateFileQueryWithOptions(queryOptions).GetFilesAsync(); foreach (var video in videos) { //Debug.WriteLine(video.Name); //videoItems.Add(new VideoListItem()); var bitmap = new BitmapImage(); var thumbnail = await video.GetThumbnailAsync(ThumbnailMode.SingleItem); await bitmap.SetSourceAsync(thumbnail); videoItems.Add(new VideoListItem(video.DisplayName,””,new Uri(video.Path),bitmap)); } //foreach(var video in videoItems) //{ // Debug.WriteLine(“Name:{0},Author:{1},Uri:{2},Bitmap:{3}”,video.VideoName,video.Author,video.Vid_url,video.Image.UriSource); //} return videoItems; }}}

4)Video.xaml

<Page xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation” xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml” xmlns:local=”using:UWP.Views” xmlns:d=”http://schemas.microsoft.com/expression/blend/2008″ xmlns:mc=”http://schemas.openxmlformats.org/markup-compatibility/2006″ xmlns:Controls=”using:Microsoft.Toolkit.Uwp.UI.Controls” x:Class=”UWP.Views.Video” mc:Ignorable=”d” NavigationCacheMode=”Enabled” DataContext=”{Binding Source={StaticResource viewmodelLocator},Path=VideoListModel}”><!–NavigationCacheMode Enable for the page state save–><Page.Resources> <DataTemplate x:Key=”VideoTemplate”> <Grid Width=”{Binding Width}” Height=”{Binding Height}” Margin=”2″> <Image HorizontalAlignment=”Center” Stretch=”UniformToFill” Source=”{Binding Image}” /> <TextBlock Text=”{Binding VideoName}”/> <StackPanel Orientation=”Horizontal”> <TextBlock Text=”Author” /> <TextBlock Text=”{Binding Author}” /> </StackPanel> </Grid> </DataTemplate></Page.Resources><Grid Background=”{ThemeResource ApplicationPageBackgroundThemeBrush}”> <ListView Name=”VideosListWrapPanal” ItemTemplate=”{StaticResource VideoTemplate}”> <ItemsControl.ItemsPanel> <ItemsPanelTemplate> <Controls:WrapPanel /> </ItemsPanelTemplate> </ItemsControl.ItemsPanel> </ListView></Grid></Page>

我想在我的VideoListModel中为构造函数执行类似下面的操作.

public async Mainviewmodel(){ VideoItems = new ObservableCollection<MainMenuItem>(await GetVideoItem());}

如何以异步方式完成此初始化?
为了获得缩略图,我创建了GetVideoItem()的方法,
但我找不到在构造函数中异步调用GetVideoItem的方法.
有谁知道如何解决这个任务?

解决方法 我建议使用异步任务通知程序,如我在 async MVVM data binding上的文章中所述.

例如,使用this helper library的NotifyTask:

public NotifyTask<List<VideoListItem>> VideoItems { get; }public VideoListModel(IKNownFolderReader kNownFolder){ _kNownFolder = kNownFolder; VideoItems = NotifyTask.Create(() => _kNownFolder.GetData());}

然后,您的数据绑定将从ItemsSource =“{Binding VideoItems}”更改为ItemsSource =“{Binding VideoItems.Result}”.此外,VideoItems还有其他几个属性,如IsNotCompleted和IsFaulted,因此您的数据绑定可以根据任务的状态显示/隐藏元素.

这种方法避免了细微的problems with Result和problems with ContinueWith.