在任务工厂 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());
您可能需要考虑是要处理所有发生的事件还是只处理最后一个事件,在这种情况下,单个变量就足够了,而不是队列。
我有一个绑定到 属性 的列表。还有一个加载事件 "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());
您可能需要考虑是要处理所有发生的事件还是只处理最后一个事件,在这种情况下,单个变量就足够了,而不是队列。