为什么从组合框进行选择后切换图形需要更长的时间

本文关键字:图形 时间 组合 行选 选择 为什么 | 更新日期: 2023-09-27 18:31:03

我有一个绘制指南针的 WPF 应用程序。有一个带有刻度线和标签的大环。我有一个复选框,可以打开和关闭指南针图形。当我第一次启动应用程序时,指南针会立即打开和关闭。

同时,我有一个组合框,可以从本地数据库中获取一些数据并使用它来渲染一些叠加图形。使用此组合框后,指南针图形不再快速切换。事实上,每当我单击复选框时,UI 都会完全冻结大约 4 秒。

我尝试使用 WPF 的窗口性能分析工具分析我的应用。当我激活该复选框时,不仅我的应用程序冻结了,探查器也冻结了。图表后来"赶上"了,但这告诉我一定有什么严重的问题。

我已经设法确定问题图形是刻度线(而不是数字标签)。如果我消除它们,冻结问题就会停止。如果我将它们从 360 度削减到 36 度,应用程序仍然会冻结,但时间更短。同样,无论我有多少刻度线,它们都会在应用程序首次启动时立即切换。

我的问题是,我如何弄清楚为什么指南针图形的切换从即时到非常慢?我已经尝试了广泛的分析和调试,但我只是想不出任何理由为什么在某些刻度线上设置可见性会导致应用程序冻结。

编辑

好的,我已经从我的应用程序中剥离了所有内容,只剩下最基本的东西,压缩了它,然后将其上传到Sendspace。这是链接(大约 143K):

http://www.sendspace.com/file/n1u3yg

[注意:不要不小心点击横幅广告,真正的下载链接在页面上要小得多,也低得多。

两个请求:

  1. 您在计算机上遇到问题吗?尝试打开指南针.exe(在bin''Release中)并快速单击复选框。指南针刻度线应立即打开和关闭。然后,从组合框中选择一个项目,并再次尝试快速单击该复选框。在我的机器上,它非常滞后,在我停止快速点击后,图形需要几秒钟才能赶上。

  2. 如果您确实遇到滞后,您是否在代码中看到可能导致这种奇怪行为的任何内容?组合框没有连接到任何东西,那么为什么从中选择项目会影响窗口上其他图形的未来性能呢?

为什么从组合框进行选择后切换图形需要更长的时间

虽然 ANTS 没有指出特定的性能"热点",但我认为您的技术略有缺陷,因为似乎每个即时报价都有一个负责处理单个即时报价的ViewModel,并且您单独将这些即时报价绑定到视图。您最终会为这些刻度创建 720 个视图模型,每次显示或隐藏整个指南针时,这些模型都会触发类似的事件。每次访问此字段时,还可以创建新的线几何图形。

在此类自定义绘制情况下,WPF 的建议方法是使用 DrawingVisual 并采用 WPF 呈现系统的保留模式方面。有几个可谷歌的资源谈论这种技术,但要点是声明一个从FrameworkElement继承的指南针类,以及一些从DrawingVisual继承的较小类,并使用它来渲染指南针。使用此技术,您仍然可以让 ViewModel 驱动指南针行为,但不会为指南针的每个部分提供单独的视图模型。我倾向于将指南针分解成表圈、箭头、瞄准器等部分......但您的问题可能需要不同的方法。

class Compass : FrameworkElement
{
    private readonly List<ICompassPart> _children = new List<ICompassPart>();
    public void AddVisualChild(ICompassPart currentObject)
    {
        _children.Add(currentObject);
        AddVisualChild((Visual)currentObject);
    }
    override protected int VisualChildrenCount { get { return _children.Count; } }
    override protected Visual GetVisualChild(int index)
    {
        if (index < 0 || index >= _children.Count) throw new ArgumentOutOfRangeException();
        return _children[index] as Visual;
    }
    override protected void OnRender(DrawingContext dc)
    {
        //The control automatically renders its children based on their RenderContext.
        //There's really nothing to do here.
        dc.DrawRectangle(Background, null, new Rect(RenderSize));
    }
}
class Bezel : DrawingVisual
{
   private bool _visible;
   public bool Visible {
   {
     get { return _visible; }
     set
     {
        _visible = value;
        Update();
     }
   }
   private void Update()
   {
       var dc = this.RenderOpen().DrawingContext;
       dc.DrawLine(/*blah*/);
       dc.Close();
   }
}