在以下XAML中,editPanel始终可见。只有在按F5键启动长操作时,overlayGrid才可见。 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>
除了TextBox具有焦点外,overlayGrid完全按预期显示。如果TextBox具有焦点,则在看到overlayGrid的快速闪烁之前会进行长时间操作。就好像代码是:做长操作,显示overlayGrid,折叠overlayGrid。
执行long操作并更改overlayGrid可见性的ViewModel代码如下:
Sub Refresh()
Me.Worker.Message = String.Format("Refresh started at {0}..",
Date.Now.ToString("hh:mm:ss.fff")
)
Me.Worker.Visibility = Visibility.Visible
' Give the UI a chance to update itself.
System.Windows.Forms.Application.DoEvents()
Console.WriteLine("Debug: " + Me.Worker.Message)
' Fake the long operation.
System.Threading.Thread.Sleep(1000)
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 Sub
为什么在TextBox具有焦点时,overlayGrid的实际可见性会延迟?我该如何解决这个问题?
答案 0 :(得分:2)
即使在WinForms中,也不鼓励使用System.Windows.Forms.Application.DoEvents()
的AFAIK。你肯定不应该在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