Spo*_*ock 5 asynchronous async-await c#-4.0 microsoft-metro windows-runtime
下面是一个示例实现,它使用metro API和数据绑定(使用MVVM)填充下拉列表中的文件夹列表.
View模型的构造函数使用SetFolders方法(private async),它调用一个等待的方法fileService.GetFoldersAsync()来获取文件夹列表.然后将文件夹列表分配给名为"FoldersList"的属性.XAML使用此属性使用数据绑定填充下拉列表.
我想知道是否有更好的方法来设置FoldersList属性,而不必在构造函数中设置它,如下所示.我希望调用GetFilesAsync方法并在发生实际数据绑定时设置FilesList属性值(不是在init类中).由于属性不支持async/await修饰符(据我所知),我正在努力实现一个合适的解决方案.任何想法都非常感激.
代码如下.
视图模型
public class FileViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private readonly IFileService fileService;
public FileDataViewModel(IFileService fileService)
{
this.fileService = fileService;
SetFolders();
}
private async void SetFolders ()
{
FoldersList = await fileService.GetFoldersAsync();
}
private IEnumerable< IStorageFolder > foldersList;
public IEnumerable<StorageFolder> FoldersList
{
get { return foldersList; }
private set
{
foldersList = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("FoldersList"));
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
IFileService和实现
public interface IFileService {
Task<IEnumerable<IStorageFolder>> GetFilesAsync();
}
public class FileService : IFileService
{
public async Task<IEnumerable<IStorageFolder>> GetFoldersAsync()
{
var folder = KnownFolders.DocumentsLibrary;
return await folder.GetFoldersAsync();
}
}
Run Code Online (Sandbox Code Playgroud)
我会把它实现为一个懒惰的属性ObservableCollection<T>而不是使用IEnumerable<T>.我们在几个项目中做到这一点并且效果很好.这样,您可以保证仅在需要时加载数据.此外,如果需要预取它,可以始终在构造函数或其他地方调用load方法.
作为旁注,我个人不会直接从我的ViewModels公开IStorageFolder.
private async Task LoadData()
{
if(!IsLoading)
{
IsLoading = true;
Folders = new ObservableCollection<Folder>(await fileService.GetFolderAsync());
}
IsLoading = false;
}
private ObservableCollection<Folder> _folders;
public ObservableCollection<Folder> Folders
{
get
{
if(_folders == null)
{
LoadData();//Don't await...
}
return _folders;
}
private set
{
SetProperty(ref _folders,value);
}
}
private bool _isLoading;
public bool IsLoading
{
get
{
return _isLoading;
}
private set
{
SetProperty(ref _isLoading,value);
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,您可以使用IsLoading属性来显示进度环.在加载了observable集合之后,您将能够刷新它而无需重新创建它.(_folders.Add,_folders.Remove,_folders.Clear ...)