【问题标题】:How do I keep Visual Studio's Windows Forms Designer from deleting controls?如何防止 Visual Studio 的 Windows 窗体设计器删除控件?
【发布时间】:2010-04-20 18:32:16
【问题描述】:

对于我的几种表单,我偶尔会遇到以下问题:我使用设计器(Visual Studio 2008、Windows Forms、.NET 2.0、VB.NET)编辑表单以添加组件,后来才发现进行了一些小的调整(例如,表单的大小突然改变了几个像素),并且控件被删除。这会默默地发生——事件处理方法也会自动删除它们的Handles 后缀,因此它们永远不会被调用,也不会出现编译器错误。我只是在很久以后才注意到或根本没有注意到,因为我正在处理表单中的不同区域。

例如,我有一个带有 SplitContainer 的表单,左侧包含 Infragistics UltraListView,右侧包含 UltraTabControl。我添加了一个新选项卡和其中的控件,它们运行良好。后来我发现列表视图的滚动条突然不可见,因为它的大小被关闭了,并且至少有一个控件从我没有处理的不同选项卡中删除。

这是 WinForms Designer 还是 Infragistics 的已知问题?当然,我使用版本控制,因此我可以比较更改并将已删除的代码重新合并,但这是一个乏味的过程,不应该是必要的。有没有办法避免这种情况?发生这种情况有充分的理由吗?

一个线索是,被删除的控件可能具有期望在运行时而不是设计时运行的代码(例如Load 事件处理程序),并且可能会引发异常。这会导致 Visual Studio 删除控件吗?

【问题讨论】:

  • 我很久以前就看到过这种情况,如果我不让 Visual Studio 完全渲染表单,它会丢弃一些控件。这可能是 Visual Studio 的最早版本。
  • 你的最后一段很有趣。在创建代码时,控件的关联设计器可能会发生异常(设计器本身不会这样做),这可能会中断代码生成过程。因此,罪魁祸首可能是控件设计器消失的控件之前。我以前在VS中遇到过这个问题,但找不到解释。
  • 我不认为事件处理程序中只有运行时代码可能是原因,我接手的一个以前的项目在负载处理程序中充斥着数据库读取,直到我把它放了很多“ If not DesignMode Then" 当我在设计器中打开它们时,它一直有问题,但我注意到它从未丢失任何控件。
  • 我只记得当我将控件添加到表单但后来破坏它们以使其无法构建时,自定义控件发生了这种情况,当我修复它们时,它们'从表格中消失了。不过,我从来没有能够始终如一地重现这一点,所以我不能肯定这不是我做错了什么导致了这种情况发生。
  • Infragistics 控件的代码是否生成到同一个设计器文件中?我无法想象 winform 的团队在生成程序代码以及考虑其他与该代码混淆的所有场景方面所面临的挑战。这可能是引入像 XAML 这样更具声明性的东西的一半原因。我总是遇到数据集设计器遇到类似问题的问题,即通过设计器进行的更改会消失,或者数据集设计会看似随意地完全破坏,必须删除并重新创建。

标签: .net vb.net winforms visual-studio-2008 windows-forms-designer


【解决方案1】:

这不是您问题的答案,但请记住您应该在加载时使用“DesignMode”。这样可以避免在设计时出现奇怪的意外行为。

private void EureFormAbm_Load(object sender, System.EventArgs e)
{
    if (!DesignMode)
    {
        // Your code
    } /* if */
}

private void EureFormAbm_Load(object sender, System.EventArgs e)
{
    if (DesignMode)
        return;
    // Your code
}

【讨论】:

  • +1 这是在使用 winforms 时保持理智所需要做的一部分。
  • 谢谢。这对我来说似乎是最可能的原因。
  • 将此修复应用于我描述的here 问题。
【解决方案2】:

如果您可以重现问题,那么您可以确定原因是否是异常。启动 Visual Studio 的第二个实例并使用“工具->附加到进程”附加到第一个实例。然后继续重现问题,当抛出未处理的异常时,代码应该会中断。有关其他异常(可能已处理)的信息将显示在“输出”窗口中。

【讨论】:

    【解决方案3】:

    这对你来说不是一个真正的答案,但这里有一些我发现对你有帮助的建议..

    一) 请参阅@Daniel Dolz 的回答。我全心全意地建议您始终按照他的建议行事,除非您完全避免将非 UI 代码(或任何代码)放在 Form_Load 中。这实际上解决了很多问题,尤其是那些在设计师中出现的异常和设计师表现缓慢的问题。

    B)尽可能人性化:

    永远不要编辑Windows Forms中的designer.cs

    好的,有时您必须这样做,但这不是进行常规开发的地方。第三方控件会有需要您这样做的错误,但是当您在设计器文件中进行直接更改时,这应该是极其罕见的一天。帮助管理此问题的一种方法是,如果您不希望设计器自动调整某些内容,请将其复制到您的常规 .cs 文件中。这并不能涵盖所有内容,但请记住这一点。

    C) 另外,您是否知道您可以通过 IDE锁定布局,以防止鼠标点击杂乱无章地弄乱您的一切?这将抢占您遇到的一些“自动更新”。

    Parting Shot 在我当前的项目之前,我在一个大型 Windows 窗体项目上工作了两年多,我只能说,直到我们结束编辑设计师的人,除了非常小的编辑并要求他们进行设计模式检查,我们只有问题。离开网络项目后,我们很难接受这个想法,因为我们已经习惯了编辑标记,但designer.cs 与标记不同。

    【讨论】:

      【解决方案4】:

      我发现 DesignMode 属性有时会产生意想不到的结果(丹尼尔的回答)。下面是我在基本控件类上的一个属性(我创建的大多数控件都继承自此),cmets 应该指出看起来像 hacky 代码的“原因”,但本质上这比 DesignMode 本身更可靠。

          /// <summary>
          /// Indicates if the current view is being utilized in the VS.NET IDE or not.
          /// </summary>
          /// <remarks>The DesignMode property for a UserControl object will show that it is in DesignMode
          /// only if the immediate parent is viewed in the IDE; if it is a grand child of the object that is being viewed in the IDE,
          /// then the DesignMode property will not be true.
          /// This is a workaround</remarks>
          public bool InDesignMode
          {
              get
              {
                  // Site.Design mode sometimes produces a better result.
                  if (DesignMode || Site != null && Site.DesignMode)
                      return true;
                  Control parent = Parent;
                  while (parent != null)
                  {
                      if (parent.Site != null && parent.Site.DesignMode)
                          return true;
                      parent = parent.Parent;
                  }
      
                  // Note: I am not 100% sure about this one; I need to double check
                  // if in design mode then entryAssembly will be null. This check is 
                  // needed because DesignMode property is only true for the control
                  // that is actively being designed, so child controls will be false...
                  // We do check the Parent heirarchy in InDesignMode but in some 
                  // cases Parent will not be set before the check is required.
                  var entryAssembly = Assembly.GetEntryAssembly();
                  if (entryAssembly == null)
                      return true;
      
                  return false;
              }
          }
      

      【讨论】:

      • 其他人能否评论是否真的需要对 DesignMode 进行如此彻底的检查?似乎它会导致轻微的性能损失。
      • 奇怪...从来没有发生在我身上。
      【解决方案5】:

      另一个好习惯,不要删除默认的表单构造函数。 IDE 使用它们,即使您的逻辑没有。 锁定也很有用。

      【讨论】:

        【解决方案6】:

        当操作系统出现问题时,我已经看到 Visual Basic 6.0 和早期 .NET 会发生这种情况。我们必须重新启动和修复。

        【讨论】:

        • 我已经在多个虚拟机上看到过这种情况,即不同的 VS 安装。
        • @Dave- 这是一个非常正常的 VS.Net/WinForms 问题。
        猜你喜欢
        • 2012-01-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-10-30
        • 2012-02-15
        • 1970-01-01
        相关资源
        最近更新 更多