当文本框有焦点时,为什么WPF网格的可见性会延迟?
在以下XAML中,editPanel始终可见。只有按F5键启动长时间操作后,才能看到重叠网格。editPanel灰显的视觉效果将在长过程中发生当文本框有焦点时,为什么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
<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