Binding data from WCF into a MVVM client always empty

被刻印的时光 ゝ 提交于 2019-12-08 21:32:29

async methods return before they have finished executing. You're not seeing any users because GetUsers returned to the UserRepository constructor which returned to the UsersViewModel constructor before the users were loaded.

The solution I most prefer is asynchronous factory methods, e.g., for UserRepository:

private UserRepository()
{
}

private async Task InitializeAsync()
{
    var tempList = await _client.GetUsersAsync();
    foreach(UserDTO item in tempList)
    {
        _users.Add(item);
    }
}

public static async Task<UserRepository> Create()
{
    var ret = new UserRepository();
    await ret.InitializeAsync();
    return ret;
}

The biggest benefit of the async factory method approach is that you never get an instance that hasn't been initialized.

However, there are certain situations where you must have a public constructor rather than an async factory method, e.g., IoC/DI or data binding.

In cases like these, I find the following pattern helpful:

public MyConstructor()
{
  Initialized = InitializeAsync();
}

public Task Initialized { get; private set; }
private async Task InitializeAsync()
{
  // asynchronous initialization here
}

You could apply it to your repository like this:

private ObservableCollection<UserDTO> _users = new ObservableCollection<UserDTO>();
private ServiceClient _client = new ServiceClient();

public UserRepository()
{
    Initialized = InitializeAsync();
}

public Task Initialized { get; private set; }
private async Task InitializeAsync()
{
    var tempList = await _client.GetUsersAsync();
    foreach(UserDTO item in tempList)
    {
        _users.Add(item);
    }
}

You can then use the same pattern in your dependent class:

public UsersViewModel()
{
    _repo = new UserRepository();
    Initialized = InitializeAsync();
}

public Task Initialized { get; private set; }
private async Task InitializeAsync()
{
    // Wait for the repository to initialize
    await _repo.Initialized;

    foreach (UserDTO item in _repo.Users)
    {
        _users.Add(new UserViewModel(item.Id));
    }
}

As a side note: as a general rule you should avoid async void. You may find my async/await intro helpful.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!