0

I have a List that is bound to a property. There is a load event too "ListLoaded".

<ListView ScrollViewer.HorizontalScrollBarVisibility="Hidden" ScrollViewer.VerticalScrollBarVisibility="Hidden" BorderThickness="0" HorizontalAlignment="Left" ItemsSource="{Binding DoctorDetailsBooking,Mode=TwoWay}">
    <i:Interaction.Triggers>
         <i:EventTrigger EventName="Loaded">
             <cmd:EventToCommand Command="{Binding ListLoaded}" PassEventArgsToCommand="True" />
          </i:EventTrigger>
    </i:Interaction.Triggers>

On its load event, I am setting the 1st selected item to true and changing the background color of that item.

Some operations and API calls are made in the constructor of the ViewModel. The load event is also set in the constructor. It takes some time to load the screen. So I added the entire code in constructor in the Task Factory and set the progress bar visibility accordingly.

Task tskOpen = Task.Factory.StartNew(() =>
            {
                ProgressBarVisibility = Visibility.Visible;

                DataAccess data = new DataAccess();
                DoctorDetailsBooking = data.GetDoctorsList(Convert.ToDateTime(BookingDate).Date);
                FillSlots();
                **ListLoaded = new RelayCommand<RoutedEventArgs>(ListViewLoaded);**

            }).ContinueWith(t =>
                {
                    ProgressBarVisibility = Visibility.Hidden;
                }, TaskScheduler.FromCurrentSynchronizationContext());    

The issue is, when I give the code inside the Task, the ListeViewLoaded event does not fire. Hence, the list view is not loaded properly. If I remove the Task portion of code, the event is fired and everything works well.

I do not know threading and Task concept well. Am I missing something here?

Ani_1317
  • 151
  • 1
  • 3
  • 12
  • 1
    Probably the control is loaded before the `ListLoaded` command is set inside the task, so I'd suggest you move the `ListLoaded` assignment before the task. – Grx70 Feb 04 '15 at 07:26
  • But the ListLoaded uses some properties that are being set in FilleSlots() method. So when I moved the assignment above the task, its not loaded properly. Similarly, when I moved the assignment after the task, the list loads first and then the methods are fired (as they are inside the task). – Ani_1317 Feb 04 '15 at 08:30

1 Answers1

1

If I understand you correctly you're facing deferred event handling - that is handling events not immediately, but after some condition is met. What I would do is to store fired events' arguments in a collection and then invoke the handlers after the condition is met. In your case it would be something similar to this:

//create a queue to store event args
var deferredEventArgs = new Queue<RoutedEventArgs>();
//temporarily assign a handler/command that will store the args in the queue
ListLoaded = new RelayCommand<RoutedEventArgs>(e => deferredEventArgs.Enqueue(e));

Task tskOpen = Task.Factory.StartNew(() =>
{
    ProgressBarVisibility = Visibility.Visible;
    DataAccess data = new DataAccess();
    DoctorDetailsBooking = data.GetDoctorsList(Convert.ToDateTime(BookingDate).Date);
    FillSlots();

    //assign the proper handler/command once its ready
    ListLoaded = new RelayCommand<RoutedEventArgs>(ListViewLoaded);

}).ContinueWith(t =>
{
    //"flush" the queue - handle previous events
    //decide whether it should be done on the UI thread
    while(deferredEventArgs.Any())
        ListViewLoaded(deferredEventArgs.Dequeue());
    ProgressBarVisibility = Visibility.Hidden;
}, TaskScheduler.FromCurrentSynchronizationContext());

You may want to consider whether you want to handle all events that occurred or only the last one, in which case single variable will suffice instead of a queue.

Grx70
  • 10,041
  • 1
  • 40
  • 55
  • I have posted another doubt in the below link. Could you please help if you have time? http://stackoverflow.com/questions/28320641/task-in-click-event-does-not-handle-ui-related-changes-wpf – Ani_1317 Feb 04 '15 at 12:24