0

I am trying to bind data to a grid using MVVM Light. If I do the following it works:

public class GuidePageViewModel : ViewModelBase
{
    private ObservableCollection<SimpleChannelData> _simpleChannelDataList;
    private IChannelDataService _channelDataService;

    public GuidePageViewModel(IChannelDataService channelDataService)
    {
        _channelDataService = channelDataService;

        ATest(); // Create data synchronously here
    }

    private void ATest()
    {
        SimpleChannelDataList = new ObservableCollection<SimpleChannelData>();

        var record = new SimpleChannelData()
        {
            Cn = 120,
            Csign = "Hey",
            Hd = "Y",
            Index = 1,
            Premium = "y",
            TrbId = 9
        };

        SimpleChannelDataList.Add(record);
    }

    private async void Start()
    {
        await LoadChannelData();
    }

    private async Task LoadChannelData()
    {
        SimpleChannelDataList = new ObservableCollection<SimpleChannelData>((await _channelDataService.GetChannelData()));
        RaisePropertyChanged(() => SimpleChannelDataList);
    }

    #region Public Properties

    public ObservableCollection<SimpleChannelData> SimpleChannelDataList
    {
        get
        {
            return _simpleChannelDataList;
        }
        set
        {
            if (Set(() => SimpleChannelDataList, ref  _simpleChannelDataList, value))
            {
                RaisePropertyChanged(() => SimpleChannelDataList);
            }

        }
    }
    #endregion
}

Now, if I change the constructor to the following instead, using an asynchronous call to Start, the grid does not get the data:

public GuidePageViewModel(IChannelDataService channelDataService)
{
    _channelDataService = channelDataService;
    Start();
}

I know this some sort of Async issue, but I cannot figure it out. Can someone point out what I am doing wrong?

poke
  • 369,085
  • 72
  • 557
  • 602
MrTouya
  • 656
  • 6
  • 19
  • I cannot reproduce your problem. Calling an `async void` method from synchronous methods should work fine (although being dangerous). Can you provide a [minimal example](http://stackoverflow.com/help/mcve) that we can run? – poke Mar 31 '15 at 06:44

1 Answers1

0

At first, you should not call async methods in the constructor. Try to change your logic so that that call is not required.

In mean time, try to check AsyncMVVM. It contains some interesting patterns to retrieve in an async way the data while exposing the usual MVVM interface.

Community
  • 1
  • 1
Vincenzo
  • 1,549
  • 1
  • 9
  • 17
  • Why the link to this very question? I was expecting some information on why not to call async void methods in a constructor. And this does not really answer the question. – poke Mar 31 '15 at 06:25
  • I gave you informations on that. Check the link on the "Constructor" word :) – Vincenzo Mar 31 '15 at 06:36
  • As I said, that link leads to *this* question. – poke Mar 31 '15 at 06:42
  • Whoops! Sorry! [Here](http://stackoverflow.com/questions/8145479/can-constructors-be-async) – Vincenzo Mar 31 '15 at 07:17
  • Okay, that link is better. However, it still doesn’t explain why you “should not call async methods in the constructor”. It only explains why it’s not possible for a constructor to be asynchronous. But it even explicitly mentions the fire-and-forget idea of calling an `async void` method from within the constructor. Because calling an `async void` method is a good way to start an asynchronous process from within any synchronous method—including constructors. OP’s code is fine and should be working; and this still does not answer the question (which I’d say is currently impossible to answer). – poke Mar 31 '15 at 07:27
  • The first answer provides a more-or-less clear explanation on that. About your issue, I'll be more than happy to provide a full example as soon as possible. – Vincenzo Mar 31 '15 at 07:42