繁体   English   中英

WPF MVVM-在显示视图之前未在ViewModel中应用绑定(异步/等待)

[英]Wpf MVVM - Binding not applied in ViewModel before View is showing (Async / await)

当我尝试在ViewModel中绑定ObservableCollection时,出现一个小错误。 问题是它连接到Web api来获取列表,但是由于某种原因,它不够快。

我认为这与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绑定到名称= List的列表,则它可以工作(足够快),但是在绑定到AvailableRooms时它不起作用。

我真的不希望在可以单击的视图中使用searchCommand,只希望在显示视图之前填充列表。

有任何想法吗?

问题是async void 如果要等待方法,则其返回类型必须为TaskTask<T>

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

在ctor中,您无法等待此方法,因此可以像这样简单地调用此方法:

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

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

    // ...
}

更新:

您还应该在视图模型中实现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
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM