Visual Studio 2008 IDE不能正确地渲染自定义控件

5
我在Visual Studios 2008中的所有表单和自定义控件在设计时遇到了问题。在上次检查之前,所有控件都按预期渲染。当前版本和上一个工作版本之间唯一的主要区别是,控件UIText上的属性Content已重命名为Value。其他更改包括添加一个新表单和3个新枚举,但显然没有明显的更改会影响程序中的所有表单(包括新表单)。
现在所有控件(在每个表单上)都呈现为带有控件名称的框(但在运行时它们都正确地呈现):
注意,标准的.Net表单控件正常工作,因此这只是自定义控件的问题。
如果我从存储库中恢复以前的版本,那么一切都会再次正确呈现。
我可以回退到这个工作版本并继续进行,但如果再次出现问题,我宁愿知道如何解决问题。我在这里发布希望它是一个编程问题而不是Visual Studios 2008问题(顺便说一下,我使用的是SP1)。
更新-问题已跟踪,无法解释
我修复了问题。好吧,修复并不是真正正确的词。我通过逐个删除所有用户控件直到表单再次正确呈现来定位问题。问题出在我的Signature控件上(它已经存在很长时间,只是在我最新的检查中,我将对项目iVirtualDocket.CodeLibrary的引用添加到了主项目中:
  iVirtualDocket
    - References iVirtualDocket.UIControls
    - References iVirtualDocket.CodeLibrary
  iVirtualDocket.UIControls
    -References iVirtualDocket.CodeLibrary

签名有一个叫做SignatureData的属性,它会执行以下操作:
public byte[] SignatureData
{
    get
    {
        if (_signature == null)
        {
            return null;
        }
        else
        {
            return iVirtualDocket.CodeLibrary.Conversions.ImageToByteArray(
                _signature, ImageFormat.Png);
        }
    }
}

ImageToByteArray的代码如下:

public static byte[] ImageToByteArray(Image imageToConvert,
        ImageFormat formatOfImage)
{
    byte[] ret;
    using (MemoryStream ms = new MemoryStream())
    {
        imageToConvert.Save(ms, formatOfImage);
        ret = ms.ToArray();
    }

    return ret;
}

如果我将上述方法移动到UIControls项目中,那么一切都可以正常工作。然而,只要我把该方法放回CodeLibrary项目并在那里调用它,所有的表单都停止呈现用户控件。
因此,以下操作可以解决问题,但我真的想知道为什么:
public byte[] SignatureData
{
    get
    {
        if (_signature == null)
        {
            return null;
        }
        else
        {
            // Need to call this code directly here instead of through 
            // the CodeLibrary conversions, otherwise all user controls stop 
            // rendering in design mode
            byte[] ret;
            using (MemoryStream ms = new MemoryStream())
            {
                _signature.Save(ms, ImageFormat.Png);
                ret = ms.ToArray();
            }

            return ret;
        }
    }
}

更离奇的是,我甚至还没有使用这个属性。

1
@Phil - 这是同样的方法,只是一个打字错误。 - djdd87
没有捕获到VS错误。而且,这还不够,因为我在我的属性中进行了空值检查 - djdd87
1
你能否发布一个完整但是简化的解决方案来展示问题吗? - Phil
3
我会尽快制作一个可复现的版本。 - djdd87
当它开始正常工作时,你是否重新尝试了之前的方法,但仍然没有成功? - Chibueze Opata
显示剩余8条评论
3个回答

2
我们有一个应用程序,也遇到了类似的非设计时显示问题。通过一些研究(我不记得具体是在哪里找到的),我们最终创建了一个名为“DesignTimeAttributes.xmta”的文件。
它的类型是“Design-Time Attribute File”,我们只需声明我们定义的每个控件类并将其标识为“DesktopCompatible”。这样,它似乎告诉设计师可以绘制,而某些控件内部的实际功能(对于我们来说,还包括手持扫描仪上的签名控件)在运行时会实际调用一些在设计者中不可用的内容。文件的内容大致如下...
<?xml version="1.0" encoding="utf-16"?>
<Classes xmlns="http://schemas.microsoft.com/VisualStudio/2004/03/SmartDevices/XMTA.xsd">
  <Class Name="MyNamespace.MyControl">
    <DesktopCompatible>true</DesktopCompatible>
  </Class>

  <Class Name="MyNamespace.MyOtherControl">
    <DesktopCompatible>true</DesktopCompatible>
  </Class>

  <Class Name="AnotherNamespace.MySignControl">
    <DesktopCompatible>true</DesktopCompatible>
  </Class>
</Classes>

除了csauve的答案提供的评论外,还需要补充一些内容。如果您的构造函数试图初始化某些与设备有关的东西,并因为设计时没有设备dll、控件或其他东西而引发错误,这也可能会在设计时杀死该控件。我们已经创建了两个静态函数来测试两种方式:

public static bool IsDesignTime()
{
  return System.ComponentModel.LicenseManager.UsageMode ==
         System.ComponentModel.LicenseUsageMode.Designtime;
}

public static bool IsRunTime()
{
  return System.ComponentModel.LicenseManager.UsageMode ==
         System.ComponentModel.LicenseUsageMode.Runtime;
}

并在构造函数中分别调用它们...


当我使用 DllImport 时,我再次遇到了同样的问题。我所要做的就是创建 DesignTimeAttributes.xmta 文件,这样就解决了之前的问题。 - djdd87
@DRapp,xmta设置没问题,但是在.NET Compact Framework (.netcf)中,“LicenseManager”类不可用。项目无法编译。我会为此提供另一个答案。 - antonio

0

我认为你可能需要让你的控件知道它们何时处于设计模式。如果可以避免,你的控件的无参构造函数不应执行任何既昂贵又具有副作用(例如从磁盘加载文件)的操作。

我假设你正在使用WPF。我相信可以使用DesignerProperties.GetIsInDesignMode(this)来确定设计模式。

请参见http://msdn.microsoft.com/en-us/library/system.componentmodel.designerproperties.getisindesignmode.aspx

public partial class MyControl : UserControl
{
   public MyControl()
   {
      InitializeComponent();
      if (!DesignerProperties.GetIsInDesignMode(this))
      {
        //Do expensive operations here
      }
   }
}

您可能还想阅读http://blogs.msdn.com/b/jgalasyn/archive/2007/10/29/troubleshooting-wpf-designer-load-failures.aspx以解决WPF设计师加载失败的问题。


嗨,这不是WPF。这是Visual Studios 2008中的WM6(Compact Framework)。这不是问题,因为如我先前所说,属性未被调用(在我的构造函数或任何地方)。 - djdd87
哦,好的,抱歉我没能帮上忙。 - csauve

0

当你的组件(UserControl、Form、Component)的设计师部分无法在Visual Studio设计师编辑器中呈现时, 最简单的方法是将“ClassDiagram”添加到项目中,右键单击项目名称,选择项目上下文菜单,查看类图。 编辑类的自定义属性(见图),会自动在“DesignTimeAttributes.xmta”中添加条目,我们也可以为“属性”设置自定义属性。 ClassDiagram/xmta Adding custom attributes to properties

正如我上面所评论的,LicenseManager类在'NETCF'中不可用。 然后我们可以使用以下方法:

using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;

namespace SmartDeviceCommon
{
    public static class SmartDeviceApplication
    {
        public static bool DesignTime
        {
            get
            {
                return Environment.OSVersion.Platform != PlatformID.WinCE;
            }
        }

        public static bool RunTime
        {
            get
            {
                return Environment.OSVersion.Platform == PlatformID.WinCE;
            }
        }

        public static bool IsDesignTime()
        {
            // Determine if this instance is running against .NET Framework by using the MSCoreLib PublicKeyToken
            System.Reflection.Assembly mscorlibAssembly = typeof(int).Assembly;
            if ((mscorlibAssembly != null))
            {
                if (mscorlibAssembly.FullName.ToUpper().EndsWith("B77A5C561934E089"))
                {
                    return true;
                }
            }
            return false;
        }

        public static bool IsRunTime()
        {
            // Determine if this instance is running against .NET Compact Framework by using the MSCoreLib PublicKeyToken
            System.Reflection.Assembly mscorlibAssembly = typeof(int).Assembly;
            if ((mscorlibAssembly != null))
            {
                if (mscorlibAssembly.FullName.ToUpper().EndsWith("969DB8053D3322AC"))
                {
                    return true;
                }
            }
            return false;
        }

    }

}

如果不起作用,那么使用@Phil的第一条评论:以管理员权限启动另一个Visual Studio实例,附加到第一个实例,使用第一个实例,在自定义用户控件上双击设计器加载,未呈现的组件可能包含平台特定的调用(dllimport)或其他错误。
最后,您可以清除appData中的CoreCon文件夹,如("C:\Users\anton\AppData\Local\Microsoft\CoreCon\1.0"),将'anton'更改为您的用户名。(在此之前关闭Visual Studio)
希望这能帮助任何人,netcf已被弃用并缺乏文档。
安东尼奥

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接