当文本框有焦点时,为什么WPF网格的可见性会延迟?

当文本框有焦点时,为什么WPF网格的可见性会延迟?,wpf,vb.net,grid,visibility,Wpf,Vb.net,Grid,Visibility,在以下XAML中,editPanel始终可见。只有按F5键启动长时间操作后,才能看到重叠网格。editPanel灰显的视觉效果将在长过程中发生 <Window.InputBindings> <KeyBinding Key="F5" Command="{Binding Path=RefreshCommand}"/> </Window.InputBindings> <Grid> <StackPanel Name="editPa

在以下XAML中,editPanel始终可见。只有按F5键启动长时间操作后,才能看到重叠网格。editPanel灰显的视觉效果将在长过程中发生

<Window.InputBindings>
    <KeyBinding Key="F5" Command="{Binding Path=RefreshCommand}"/>
</Window.InputBindings>

<Grid>

    <StackPanel Name="editPanel">
        <TextBox>set focus here to see the problem.</TextBox>
        <CheckBox>set focus here to remove the problem.</CheckBox>
        <TextBlock Text="{Binding Path=Worker.Message}"/>
    </StackPanel>

    <Grid Name="overlayGrid" 
          Visibility="{Binding Path=Worker.Visibility}"
          Background="Gray" Opacity="0.5">

        <TextBox Text="{Binding Path=Worker.Message}" FontWeight="Bold" 
                 HorizontalAlignment="Center" VerticalAlignment="Center" 
                 />

    </Grid>

</Grid>

当文本框有焦点时,OverlyGrid的实际可见性为什么会延迟?如何解决此问题?

AFAIK,即使在WinForms中也不鼓励使用
System.Windows.Forms.Application.DoEvents()
。您当然不应该在WPF中使用它,即使它起作用(显然,它不起作用)

相反,您应该在后台线程上运行长操作,然后使用
Dispatcher.Invoke()
在UI上设置结果。比如:

Sub Refresh()

    Me.Worker.Message = String.Format("Refresh started at {0}..",
                                      Date.Now.ToString("hh:mm:ss.fff")
    )

    Me.Worker.Visibility = Visibility.Visible

    Console.WriteLine("Debug: " + Me.Worker.Message)

    Task.Factory.StartNew(
        Function()
            ' Fake the long operation.
            System.Threading.Thread.Sleep(10000)

            Dispatcher.Invoke(
                Function()
                    Me.Worker.Message = String.Format("Refresh completed at {0}.",
                                                      Date.Now.ToString("hh:mm:ss.fff")
                    )

                    Me.Worker.Visibility = Visibility.Collapsed

                    Console.WriteLine("Debug: " + Me.Worker.Message)

                End Function)

        End Function)

End Sub

你的解决方案确实有效。然而,在我的“真实”程序中,我有一个多个列表框,绑定到在长时间操作期间更新的可观察集合。当然,这会因为后台线程而引发异常。因此,我尝试使用单线程。@Tim,您永远不应该在UI线程上执行任何长操作,因为这样会阻止它。每次修改集合时使用
Dispatcher.Invoke()
,或者缓存更改,然后在操作完成后立即执行所有修改。
Sub Refresh()

    Me.Worker.Message = String.Format("Refresh started at {0}..",
                                      Date.Now.ToString("hh:mm:ss.fff")
    )

    Me.Worker.Visibility = Visibility.Visible

    Console.WriteLine("Debug: " + Me.Worker.Message)

    Task.Factory.StartNew(
        Function()
            ' Fake the long operation.
            System.Threading.Thread.Sleep(10000)

            Dispatcher.Invoke(
                Function()
                    Me.Worker.Message = String.Format("Refresh completed at {0}.",
                                                      Date.Now.ToString("hh:mm:ss.fff")
                    )

                    Me.Worker.Visibility = Visibility.Collapsed

                    Console.WriteLine("Debug: " + Me.Worker.Message)

                End Function)

        End Function)

End Sub