【问题标题】:Fix display garbage left by WPF dialog window?修复 WPF 对话框窗口留下的显示垃圾?
【发布时间】:2011-01-18 01:02:10
【问题描述】:

在我的 WPF 应用程序中,我有可以打开其他 WPF 对话框窗口的 WPF 窗口,我的操作如下:

PickForEveryone PickForEveryoneWindow = new PickForEveryone(sSelRecipe, selMRM.sDay, selMRM.MealTypeID);
PickForEveryoneWindow.Owner = this;
PickForEveryoneWindow.ShowDialog();

PickForEveryone 定义为:

public partial class PickForEveryone : Window

<Window x:Class="PFWb0.PickForEveryone"
 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 xmlns:dg="http://schemas.microsoft.com/wpf/2008/toolkit"
 ShowInTaskbar="False"
 Title="Pick Recipe For All" Height="536" Width="441" 
 WindowStartupLocation="CenterOwner">

并包含一个带有 DataGrid 和几个按钮和复选框的 Grid。

这在我的开发计算机上运行良好。但是,当对话框窗口关闭时,我的客户一直看到对话框窗口的一部分显示在父窗口的顶部留下了视觉垃圾。也就是说,当 ShowDialog() 返回时,只有部分窗口未绘制。

我尝试添加 this.InvalidateVisual();在上面的代码下面,但它并没有解决问题。

我在这里也看到了一个建议(针对另一种 WPF 显示问题)调用 OnRender() 来强制重绘,但是 OnRender 需要一个 DrawingContext 类型的参数,我不知道如何获取。

所以,我想问是否有人知道如何首先解决显示问题,或者如何通过让 WPF 重绘窗口来从中恢复。

更新:正如 cmets 对下面建议的答案所见,我仍然没有适用于我客户计算机的解决方案,而且我的解决方法(让 Windows 相互闪避)已经不够了。唯一有效的方法是最小化和最大化被污染的底层窗口。

【问题讨论】:

  • 特定计算机上的图形“错误”很可能是该计算机上显示驱动程序错误的结果。如果问题出在 DirectX 中,则 WPF 可以触发问题,而 Windows 窗体应用程序不会。
  • 是的。几年前我在 MSDN 论坛上发现了相关的投诉,但没有人解决。此外,我的客户正在为他的视频适配器运行最新的驱动程序(当然,这并不意味着它没有错误,但这意味着通过更新驱动程序无法轻松修复)。此外,他实际上尝试插入不同的视频卡,它仍然在他的机器上显示该问题。我认为此时可能是 Vista,或者更准确地说,是您所说的 - 一些特定的驱动程序。

标签: wpf dialog redraw


【解决方案1】:

我在一台配备 ATOM N270 处理器的特定计算机上遇到了类似的问题。 该问题似乎与图形硬件加速有关。

要停用加速,只需将其添加到注册表(这将停用所有 WPF 应用程序的硬件加速):

HKEY_CURRENT_USER\SOFTWARE\Microsoft\Avalon.Graphics\DisableHWAcceleration

我必须创建Avalon.Graphics 文件夹。

DisableHWAcceleration 是一个DWORD,必须设置为1

这解决了我的问题,如果我重新激活加速,问题又回来了。

希望这会有所帮助。

参考资料:

【讨论】:

  • 啊哈!我非常喜欢这个建议......我会试一试!
【解决方案2】:

这个丑陋的代码对我有用:

        void RefreshWindow()
    {
        switch (WindowState)
        {
            case WindowState.Maximized:
                {
                    double oldWidth = Width;
                    Width = System.Windows.SystemParameters.PrimaryScreenWidth - 1;
                    WindowState = System.Windows.WindowState.Normal;
                    WindowState = System.Windows.WindowState.Maximized;
                    Width = oldWidth;
                }
                break;
            case WindowState.Normal:
                if (Width > 1)
                {
                    Width -= 1;
                    Width += 1;
                }
                else
                {
                    Width += 1;
                    Width -= 1;
                }
                break;
            case WindowState.Minimized:
            default:
                // no action necessary
                break;
        }
    }

【讨论】:

  • 好的,我的移动窗口使它们不重叠的解决方法已经被我的应用程序所超越,现在有时需要更多的屏幕空间,所以重叠不是那么容易避免的。所以,我明天要在客户的电脑上试试这个。谢谢港铁的建议。我很好奇这是否可行,我知道后会在这里发帖。
【解决方案3】:

所以我一直在 MS 论坛上寻找这个问题的答案,显然,这个问题的变体已经问了好几年了。

他们说,有时,问题与视频驱动程序有关,尽管就我而言,我的客户最近更新了他的视频驱动程序。

我的印象是,微软认为他们设计 WPF 是为了让开发人员永远不需要做强制重绘显示这样的事情,所以他们没有办法通过设计来这样做。当然,无论出于何种原因出现问题,这意味着没有直接的方法可以做到这一点。看起来他们可能会这样做的方式(例如 InvalidateVisual()),不要这样做。

但我确实找到了一种可行的方法。嗯,两个。丑的是告诉窗口最小化并恢复正常。但这会导致它这样做的视觉动画,这并不理想。就我而言,它还让它隐藏在其他打开的窗口后面,需要我让它去最上面。但它确实以一种不和谐的方式解决了问题。

ShowDialog 之后的代码:

    this.WindowState = WindowState.Minimized;
    this.WindowState = WindowState.Normal;
    this.Topmost = true;

更好的hack,看起来有点像这样:

代码外:

public delegate void NoArgDelegate();

ShowDialog 之后的代码:

    this.Dispatcher.Invoke(
    System.Windows.Threading.DispatcherPriority.Loaded,
        (NoArgDelegate)delegate {}
    );

Presto ala kazzam!

【讨论】:

  • 哦,哎呀,显然这并不能完全解决问题。如果有人知道对这个问题有什么贡献,请告诉我。
  • 我试过UpdateLayout(),没有效果。我现在还尝试在关闭对话框窗口之前使其最小化。那也没用。
  • 然后我添加了代码以将对话框窗口移动到屏幕外坐标,然后将其最小化,然后将其关闭,但这也不起作用。它确实改变了我的开发计算机上的“消失”动画,使其闪烁而不是缩小然后消失,但它仍然在父窗口上留下垃圾。
  • 但是,我的客户报告说,如果他手动移动对话框窗口,它会确定垃圾留在哪里,所以我认为移动窗口会起作用,如果我能在之前真正做到的话它关闭。我想通过调用更改 X 和 Y 并最小化然后关闭,位置和最小化调用在关闭生效之前没有效果。有人会如何建议我在关闭对话框窗口之前对其进行延迟或强制视觉更新?
【解决方案4】:

这个解决方案有效,但不是很漂亮(很容易看到对话框被最小化然后设置为正常)。

this.WindowState = WindowState.Minimized;
this.WindowState = WindowState.Normal;
this.Topmost = true;

【讨论】:

  • 实际上,我尝试过的所有解决方案都没有真正在客户的计算机上运行。
  • 谢谢啊。我在上面对自己的第一个“答案”中发布了那个。那个应该可以工作(以笨拙的方式工作),但我实际上并没有让我的客户运行它。如果我昨天提到的方案不起作用,我会让他试一试。
【解决方案5】:

到目前为止,我尝试过的任何东西都无法在我客户的计算机上运行。 我有一个新的修复(解决方法黑客)尝试进行客户端测试,其中涉及将窗口移开,并试图通过在我关闭对话框窗口之前启动一个空窗口来使其实际生效。叹息……

【讨论】:

  • 那次尝试也失败了。最后,我只是避免堆叠那些窗口,虽然其他窗口似乎能够堆叠而不留下垃圾,我不知道为什么这些会是一个问题而不是其他的,但因为原因似乎是一个驱动程序错误或其他东西,我想我不应该期望太多的逻辑。无论如何,使窗口不重叠的解决方法实际上是一个很好的设计转变,所以我现在放弃这个问题,但我仍然很好奇是否有人有任何东西!
猜你喜欢
  • 1970-01-01
  • 2010-12-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多