0

我有一个“加载数据”过程,可能需要 1 到 20 秒,所以我想在我的窗口上显示一条状态消息。我的窗口网格有一行将根据绑定到我的视图模型的触发器可见或隐藏。这很好用。我的问题是如何在我的长时间运行的任务开始之前更改绑定并让 UI 刷新。现在发生的情况是设置了 Status 属性,然后我开始我的任务,但 UI 直到我的任务完成后才会刷新。这是我的 xaml 和视图模型代码。

<Grid Grid.Row="4" Background="{StaticResource appPrimaryBackColorLight}" Height="20">
    <Grid.Style>
        <Style TargetType="Grid">
            <Style.Triggers>
                <DataTrigger Binding="{Binding StatusMessageVisibility}" Value="Collapsed">
                    <DataTrigger.EnterActions>
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation Storyboard.TargetProperty="Height" From="20" To="0" Duration="0:0:0.1" />
                            </Storyboard>
                        </BeginStoryboard>
                    </DataTrigger.EnterActions>
                    <DataTrigger.ExitActions>
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation Storyboard.TargetProperty="Height" From="0" To="20" Duration="0:0:.1" />
                            </Storyboard>
                        </BeginStoryboard>
                    </DataTrigger.ExitActions>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Grid.Style>
    <StackPanel Orientation="Horizontal" VerticalAlignment="Center">
        <Image Width="20" Height="20" Grid.RowSpan="2" ani:ImageBehavior.AnimatedSource="/Images/spinner_status_20.gif"></Image>
        <TextBlock Text="{Binding StatusMessage}" Height="20" VerticalAlignment="Center" Padding="5,1,0,0" Style="{StaticResource appTextBlockSmallDark}" Foreground="White" />
    </StackPanel>
</Grid>


private void LoadImportData() 
{
    // Show the status message by changing the view model properties
    StatusMessage = "Loading data from import file. Please stand by...";
    StatusMessageVisibility = Visibility.Visible;

    Task.Factory.StartNew(() =>
                          {
                              //This invokes UI specific code inside module initialization
                              LoadDataNow();
                          }, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.FromCurrentSynchronizationContext());
}
4

1 回答 1

2

问题是您正在为您的任务使用当前同步上下文 - 即 UI 线程。您没有在后台线程上运行它。相反,为您的工作任务使用默认参数,将其安排在单独的线程上,并创建一个延续以在 UI 线程上运行。任务完成后,此延续将更新 UI。

var task = Task.Factory.StartNew(() =>
                      {
                          //This invokes UI specific code inside module initialization
                          LoadDataNow();
                      });
task.ContinueWith(t => StatusMessageVisibility = Visibility.None, 
                       TaskScheduler.FromCurrentSynchronizationContext());
于 2013-10-02T12:24:11.227 回答