2016-04-24 42 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