在任务工厂 C# 中使用时,ListView 加载事件未触发

ListView loaded event not firing when used in Task Factory C#

我有一个绑定到 属性 的列表。还有一个加载事件 "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>

在其加载事件中,我将第一个选定项目设置为 true 并更改该项目的背景颜色。

一些操作和 API 调用是在 ViewModel 的构造函数中进行的。加载事件也在构造函数中设置。加载屏幕需要一些时间。所以我在任务工厂的构造函数中添加了整个代码,并相应地设置了进度条可见性。

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());    

问题是,当我在任务中提供代码时,ListeViewLoaded 事件没有触发。因此,列表视图未正确加载。如果我删除代码的 Task 部分,事件将被触发并且一切正常。

我不太了解线程和任务概念。我在这里遗漏了什么吗?

如果我对您的理解正确,您面临的是延迟事件处理 - 即不是立即处理事件,而是在满足某些条件后处理事件。我要做的是将触发事件的参数存储在一个集合中,然后在满足条件后调用处理程序。在您的情况下,它类似于以下内容:

//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());

您可能需要考虑是要处理所有发生的事件还是只处理最后一个事件,在这种情况下,单个变量就足够了,而不是队列。