WPF UI渲染问题

时间:2013-06-07 19:33:02

标签: c# wpf

我有一个基本的对话窗口,允许用户输入一些信息。单击AddButton时,应用程序将验证用户信息,并在操作失败时显示消息。按钮旁边有一个静态标签,最初是隐藏的。单击该按钮时,标签在验证操作开始之前变为可见,并且在操作结束后再次变为。请注意,此验证操作发生在远程计算机上,因此UI在此期间冻结(它是按设计)。

这是XAML代码:

<Label Name="lblStatus" Content="Verifying connection..." Visibility="Hidden" Grid.Column="0" />

<StackPanel Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Right">
   <Button Content="Add" Width="80" Margin="0,0,5,0" Click="AddButton_Click"/>
   <Button Content="Cancel" Width="80" IsCancel="True"/>
</StackPanel>

代码隐藏:

private void AddButton_Click(object sender, RoutedEventArgs e)
{
    lblStatus.Visibility = Visibility.Visible;

    // Validation occurs here. The UI is freezed for about 3 seconds
    Foo.Validate();

    lblStatus.Visibility = Visibility.Hidden;
}

问题是,当单击按钮时,标签在UI冻结之前不会显示。当操作失效时,会弹出一个对话框。此时,您会看到标签,但这是UI醒来的时候。这让我觉得在调用foo.Validate()时,UI没有足够的时间重新渲染标签。我想知道我的理论是否正确,以及实现这一目标的“正确”方法是什么?

2 个答案:

答案 0 :(得分:4)

private void AddButton_Click(object sender, RoutedEventArgs e)
    {
        lblStatus.Visibility = Visibility.Visible;
        Task.Factory.StartNew(()=>
            {
                Foo.Validate();
                OnUi(() => lblStatus.Visibility = Visibility.Hidden);
            }
        };
    }


public static void OnUi (Action action)
{
    if (_dispatchService == null) _dispatchService = ServiceLocator.Current.GetInstance<IDispatchService>();

     if (_dispatchService.CheckAccess())
            action.Invoke ();
        else
            _dispatchService.Invoke(action);
    }

答案 1 :(得分:-1)

之前我遇到过这个问题,以下是我解决的问题:

public class CsUtil
{
    public static void DoEvents()
    {
        Application.Current.Dispatcher.Invoke(
            DispatcherPriority.Background,
            new ThreadStart(DoNothing));
    }
    private static void DoNothing() 
    {
        // Just as it says, this method does nothing :-P
    }
}

这个类几乎可以从WinForms中获取旧的DoEvents()方法。这基本上创建了一个新线程,调用一个什么都不做的方法然后杀死线程。不知何故,这使得重点关注UI线程并且更新发生得更快。

要使用它,只需执行此操作(在代码隐藏中):

private void AddButton_Click(object sender, RoutedEventArgs e)
{
    lblStatus.Visibility = Visibility.Visible;

    // Validation occurs here. The UI is freezed for about 3 seconds
    CsUtil.DoEvents();
    Foo.Validate();

    lblStatus.Visibility = Visibility.Hidden;
}

祝你好运,如果它不起作用,请告诉我,

此致

凯尔