我有一个WPF应用程序,它是一个全屏自助服务终端应用程序。它实际上是一个非常复杂的应用程序,但这里有一些显示基本概念的代码。基本上,每当用户从一个屏幕进入下一个屏幕时,就会出现一些严重的闪烁,从而打开新窗口。在严重的情况下,桌面会在新屏幕显示之前显示几秒钟。在这个示例代码中没有发生这种情况,因为它非常简单,但添加了一些按钮和样式,你会看到它。
App.xaml.cs:
public partial class App : Application {
Manager mManager;
public App() {
mManager = new Manager();
Window1 screen1 = new Window1(mManager);
mManager.Screen1 = screen1;
try {
this.Run(screen1);
} catch (Exception e) {
System.Console.WriteLine(e.ToString());
} finally {
Application.Current.Shutdown();
}
}
}
Window1.xaml.cs:
public partial class Window1 : Window {
Manager Manager{get; set;}
public Window1(Manager inManager) {
InitializeComponent();
Manager = inManager;
}
private void OnChangeScreen(object sender, RoutedEventArgs e) {
Manager.OpenScreen2();
}
}
Window2.xaml.cs:
public partial class Window2 : Window {
Manager Manager{get; set;}
public Window2(Manager inManager) {
InitializeComponent();
Manager = inManager;
}
private void OnChangeScreen(object sender, RoutedEventArgs e) {
Manager.OpenScreen1();
}
}
Manager.cs:
public class Manager {
public Window1 Screen1{ get; set;}
public Window2 Screen2{ get; set;}
public Manager(){
Screen1 = new Window1(this);
}
public void OpenScreen2() {
Screen2 = new Window2(this);
Screen2.Show();
if (Screen1 != null) {
Screen1.Hide();
}
}
public void OpenScreen1() {
Screen1 = new Window1(this);
Screen1.Show();
if (Screen2 != null) {
Screen2.Hide();
}
}
}
Window1.xaml(基本上由window2.xaml模仿):
<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1"
WindowStyle="None"
WindowState="Maximized"
Width="1280"
Height="1024"
FontFamily="Global User Interface"
ResizeMode="NoResize">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Button Name="ChangeScreenButton" Click="OnChangeScreen" Grid.Row="2" Grid.Column="2" Content="Toggle Screen 2"></Button>
</Grid>
</Window>
交错显示两个窗口(即,在删除窗口2之前显示窗口1等)不会改变闪烁行为。在这个简单的应用程序中,可以隐藏未显示的其他屏幕,但在更复杂的应用程序中,有太多的状态信息可以正确,轻松地管理屏幕信息。
是否有一些神奇的代码字或技术可以避免闪烁,这种闪烁可以在这个简单的应用程序中运行,也可以扩展到更复杂的应用程序?我担心此时我会被迫重写整个用户界面以支持隐藏和显示,而这在我的时间框架内是不可行的。
编辑:我在某些对话框上尝试过隐藏/显示内容,这似乎并不重要。也许是因为主要的自助服务终端应用风格很重?答案 0 :(得分:15)
闪烁的根本原因是无论何时你.hide()一个窗口,PresentationSource
被断开,导致Unloaded
事件被触发到MILCore
缓存的所有内容和所有内容要丢弃的WPF层。然后当你再次.Show()
时,一切都会重建。
要防止闪烁,请确保始终将UI连接到PresentationSource。这可以通过以下几种方式完成:
带有伪装TabControl的单一窗口
使用包含TabControl
样式的单个窗口,以便您无法看到标签。通常显示或隐藏窗口时,在代码中切换选项卡。您可以使用“Page”在现有代码中搜索并替换“Window”,然后将“Show()”调用替换为您执行以下操作的自定义“Show()”:
您将用于TabControl的ContentTemplate非常简单:
<ContentTemplate TargetType="TabControl">
<ContentPresenter x:Name="PART_SelectedContentHost"
ContentSource="SelectedContent" />
</ContentTemplate>
使用带导航的框架
将Frame
与导航一起使用对于自助服务终端来说是一个非常好的解决方案,因为它实现了大量的页面切换和其他功能。但是,以这种方式更新现有应用程序可能比使用TabControl更多工作。在任何一种情况下,您都需要从Window
转换为Page
,但使用Frame时您还需要处理导航。
具有不透明度的多个窗口
您可以使用低不透明度使窗口几乎完全不可见,但WPF仍然会保留可视树。这将是一个微不足道的变化:只需将对Window.Show()
和Window.Hide()
的所有调用替换为调用“MyHide()”和“MyShow()”来更新不透明度。请注意,您可以通过让这些例程触发非常短持续时间(例如0.2秒)的动画来进一步改善这一点,从而为不透明度设置动画。由于两个动画将同时设置,动画将顺利进行,效果会很好。
答案 1 :(得分:2)
我很好奇为什么你在Kiosk中为同一个应用程序使用多个窗口。您可以轻松地将所有控件放在同一个“窗口”上,只需更改面板上的可见性即可显示不同的“屏幕”。这肯定会阻止桌面显示,并允许你做淡化过渡或滑动动画等整洁的事情。
答案 2 :(得分:1)
WPF内置了导航功能。
只需查看Frame和您可以使用VS或Blend轻松设计的Page类。
答案 3 :(得分:0)
同意有关使用内置导航功能的评论,但如果您此时已锁定设计,或许可以考虑动画窗口的不透明度?不透明度的短100或200毫秒动画,从1 - > 0表示传出窗口,0表示&gt;传入窗口的1可能会解决问题。处理故事板上Completed事件中的传出窗口的实际清理。
答案 4 :(得分:0)
看看WPF如何使用DirectX和图形处理器来卸载屏幕元素的处理,计算机的DirectX和驱动程序是最新的吗?
科里
答案 5 :(得分:0)
如果构造函数中有任何初始化需要很长时间才能导致延迟和闪烁。您可以尝试使用异步方法或将该初始化放在后台线程上,以便它不会阻止显示窗口。
可能导致延迟的一个例子是数据库查询或网络上的数据请求。
快速实验将在慢窗口中禁用部分构造函数,以找出导致显示窗口延迟的原因。
答案 6 :(得分:0)
如前所述,使用Frames / Tab Controls可以避免过渡期间的闪烁
如果您不想更改应用程序并希望在Windows7或WindowsVista上删除闪烁(桌面之间闪烁),则可以将Windows的“视觉效果”设置优化为'Adjust for best performance'
答案 7 :(得分:0)
这是一个简单的替代方案,适用于我的自助式应用程序,黑色背景,灵感来自上述答案。在这里,我有一个“LanguageWindow”,可以从应用程序的任何地方打开,以更改当前语言。
在LanguageWindow.xaml中(检查WindowState = Minimized):
<Window x:Class="LanguageWindow"
...
Title="LanguageWindow" Height="1024" Width="1280" WindowStyle="None" WindowState="Minimized" Background="Black">
在LanguageWindow.xaml.vb中:
Private Sub LanguageWindow_ContentRendered(sender As Object, e As EventArgs) Handles Me.ContentRendered
Me.WindowState = WindowState.Maximized
End Sub
瞧!
(使用Visual Studio 2015,.NET Framework 4.6,WPF,VB.net完成)