4

我有一个基本的对话窗口,允许用户输入一些信息。当他们单击 时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 唤醒的时候。这让我觉得 UI 没有足够的时间foo.Validate()在调用时重新渲染标签。我想知道我的理论是否正确,实现这一目标的“正确”方法是什么?

4

2 回答 2

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);
    }
于 2013-06-07T19:45:48.597 回答
-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;
}

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

问候,

凯尔

于 2013-06-07T19:44:52.713 回答