3

再会!

我正在编写一个 .vsix 来将旧控件替换为新控件。我有designerHost,它是当前的设计器实例。然后我开始像这样转换:

 foreach (OldCombo oldCmbx in OldCmbxs())
 {
      ...
      NewCombo newCmbx = designerHost.CreateComponent(NewComboType, oldcmbx.Name) as NewCmbx;
      ...
      newCmbx.Visible = oldCmbx.Visible;
      ...
      designerHost.DestroyComponent(oldCmbx);
 }

事情-oldCmbx总是Visible=true,无论它是如何写在 Designer.cs 文件中的。我总是在创建Visible=truenewCmbx。如果我强制 newCmbx 为Visible=false,则设计器在转换后不会显示 newCmbx ,但可见属性仍然为真,因此可见属性绝对不是我要寻找的。那么我怎样才能强制 newCmbx 出现Visible=false在 Designer.cs 中呢?

4

1 回答 1

1

在挖掘 .NET 源代码后,我发现这ControlDesigner是 .NET 的阴影Visible属性Control,因此将要序列化/反序列化的内容与ControlInitializeComponent的实际属性有很大关系。Visible

Designer.Visible属性初始化如下:

public override void Initialize(IComponent component)
{
   PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(component.GetType());
   PropertyDescriptor descriptor = properties["Visible"];
   if (((descriptor == null) || (descriptor.PropertyType != typeof(bool))) || !descriptor.ShouldSerializeValue(component))
    {
        this.Visible = true;
    }
    else
    {
        this.Visible = (bool) descriptor.GetValue(component);
    }
    ...
 }

descriptor.ShouldSerializeValue(component)forControl.Visible总是false在新创建的控件的情况下。

Designer.Visible财产:

private bool Visible
{
    get
    {
        return (bool) base.ShadowProperties["Visible"];
    }
    set
    {
        base.ShadowProperties["Visible"] = value;
    }
}

Designer.PreFilterProperties()实际Visible属性中被设计者Control的属性所掩盖。Visible

现在,当设计器被初始化时(在我创建组件时发生的代码中designerHost.CreateComponentnewCmbx.Visible总是true.

为什么会这样?因为Visible的属性Control用于绘制控件(在设计器表面上也是如此)。如果我设置newCmbx.Visible = false它只是从设计表面消失(但仍然从设计器的Visible属性中序列化) - 这很糟糕,所以通过Control类的设计,当Control被实例化时,它总是Visible可以在设计表面上可见。属性的任何后续更改都会Visible影响Visible设计器的属性,而不是 Control 本身(在设计器模式下工作的上下文中)。

所以,为了解决这个问题,我需要的是Visible设计师的财产。

正确的代码如下所示:

foreach (OldCombo oldCmbx in OldCmbxs())
{
  bool _visible = GetVisiblePropThroughReflection(designerHost.GetDesigner(oldCmbx));
  ...
  NewCombo newCmbx = designerHost.CreateComponent(NewComboType, oldcmbx.Name) as NewCmbx;
  ...
  SetVisiblePropThroughReflection(designerHost.GetDesigner(newCmbx), _visible);
  ...
  designerHost.DestroyComponent(oldCmbx);
}
于 2012-11-01T10:52:21.620 回答