在下面的XAML中,editPanel总是可见的。overlayGrid只有在按下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>
overlayGrid完全按照预期显示,除非TextBox有焦点。如果TextBox具有焦点,则在您看到overlayGrid的快速闪烁之前进行长时间操作。就好像代码是:做长操作,显示overlayGrid,折叠overlayGrid。
执行长操作并更改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
为什么当文本框有焦点时,overlayGrid的实际可见性延迟?如何解决这个问题?
当然,即使在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