2016-04-24 70 views
0

当我尝试绑定ViewModel中的ObservableCollection时,出现一个小错误。问题是它连接到web api来获取列表,但由于某种原因,它不够快。Wpf MVVM - 在视图显示之前ViewModel中没有应用绑定(Async/await)

我认为它与async/await有关,它不等待列表在加载视图之前获取其数据。

代码:

public ObservableCollection<AvailableRoomModel> AvailableRooms { get; set; } 
public ObservableCollection<AvailableRoomModel> List { get; set; } 

的AvailableRooms是正确的列表,该列表只是为了测试。

public RoomsViewModel(IGetAvailableRoomsService getAvailableRoomsService) 
{ 
    //Injection 
    _getAvailableRoomsService = getAvailableRoomsService; 

    //Initialize 
    AvailableRooms = new ObservableCollection<AvailableRoomModel>(); 

    //Get all rooms 
    GetAvailableRooms(); 

    List = new ObservableCollection<AvailableRoomModel>(); 

    List.Add(new AvailableRoomModel { Id = 1, RoomNumber = "101", Occupied = true }); 
    List.Add(new AvailableRoomModel { Id = 2, RoomNumber = "102", Occupied = true }); 
    List.Add(new AvailableRoomModel { Id = 3, RoomNumber = "103", Occupied = true }); 
} 


public async void GetAvailableRooms() 
{ 
    try 
    { 
     AvailableRooms = await _getAvailableRoomsService.getRooms(); 
    } 
    catch (Exception e) 
    { 
     //TODO 
    } 

} 

在测试了,如果我在我的ItemsControl绑定到列表与NAME =列出它的工作原理(其速度不够快),但结合AvailableRooms时忽略了最低的工作。

我真的不想要一个searchCommand在视图中我可以点击,只是想在显示视图之前填充列表。

任何想法?

回答

0

问题是async void。如果您想等待某种方法,则其返回类型必须是TaskTask<T>

public async Task<IEnumerable<AvailableRoomModel>> GetAvailableRooms() 
{ 
    try 
    { 
     return await _getAvailableRoomsService.getRooms(); 
    } 
    catch (Exception e) 
    { 
     //TODO 
    } 
} 

在构造函数你不能等待这个方法,所以你可以简单地调用这个方法是这样的:

public RoomsViewModel(IGetAvailableRoomsService getAvailableRoomsService) 
{ 
    //Injection 
    _getAvailableRoomsService = getAvailableRoomsService; 

    //Get all rooms 
    AvailableRooms = 
     new ObservableCollection<AvailableRoomModel>(
      GetAvailableRooms().GetAwaiter().GetResult() 
     ); 

    // ... 
} 

UPDATE:

你也应该实现在您的视图模型,你System.ComponentModel.INotifyPropertyChanged接口必须使用完整的属性才能提高PropertyChanged事件。 ObservableCollection<T>本身实现了这个接口,但设置一个属性不会引发这个事件,除非我们提高它。

using System.ComponentModel; 
using System.Runtime.CompilerServices; 

public class RoomsViewModel : INotifyPropertyChanged 
{ 
    /* constructor goes here from previous code block */ 

    private ObservableCollection<AvailableRoomModel> availableRooms; 
    public ObservableCollection<AvailableRoomModel> AvailableRooms 
    { 
     get { return availableRooms; } 
     set { availableRooms = value; OnPropertyChanged(); } 
    } 

    private ObservableCollection<AvailableRoomModel> list; 
    public ObservableCollection<AvailableRoomModel> List 
    { 
     get { return list; } 
     set { list = value; OnPropertyChanged(); } 
    } 

    #region INotifyPropertyChanged implementation 

    public event PropertyChangedEventHandler PropertyChanged; 

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) 
    { 
     var handler = PropertyChanged; 
     if (handler != null) 
     { 
      handler.Invoke(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 

    #endregion 
} 
+0

由于某种原因,它一直挂起。我已经调试过,并检查列表是否被填充,并且确实如此。 – Mikkel

+0

为了避免挂起不是在构造函数中的房间,而是在viewmodel中使用单独的方法,并从事件处理程序(例如'Window.Loaded')中调用它,您可以在其中使用'async void'作为事件处理程序,并且可以在其中使用'await ViewModel.LoadAvailableRooms();' – Gabor