1

我正在使用 DesignSurface 类,但遇到了一个我似乎无法弄清楚的令人沮丧的问题。我从我的工具箱中拖动项目并将它们放到我的表单上没有问题,但我想修改这些项目的属性,因为它们被放置到 DesignSurface 上。因此,例如,如果我将标签拖到 DesignSurface 上,我可能会更改控件的 BackColor 的值。我知道 ToolboxItem 公开了 CreateComponents() ,它接受一个可选的属性参数,但这是由较低级别的 API 调用的,我看不到在哪里或如何覆盖它,因此我可以提供自己的值。有没有人有任何想法?谢谢!

4

2 回答 2

1

这不是答案,我只想展示我对您的问题的发现。我想你应该有你自己的方式来访问你自己的Toolbox,这个Toolbox实现了接口IToolboxService,这个接口有一个方法叫GetSelectedToolboxItem(IDesignerHost)。而且我认为您必须实现该方法来指定如何获取所选项目,我认为您Toolbox应该有一些控制工具箱项目列表的控件,它可以是ListBox...

第二个重要的事情是IDesignerHost,据我了解,这可能是您感兴趣的内容。它应该与您的DesignSurface. 它有一些您感兴趣的事件,例如:

IDesignerHost host = {some method to get it};
host.TransactionClosed += (s,e) => {
  ICollection selected = ((ISelectionService)host.GetService(typeof(ISelectionService))).GetSelectedComponents();                
  IComponent[] comps = new IComponent[selected.Count];
  selected.CopyTo(comps, 0);
  string displayName = YourToolBox.GetSelectedToolboxItem(host).DisplayName;
  ((Control)comps[0]).Text = displayName;
};

我在一个实现非常复杂的项目中进行了测试IDesignerHost,它有一种方法可以让我创建host要测试的。当在上拖放控件时,它仍然DesignSurface不受 我没有发现任何其他事件更好,最合适的事件应该是或但它们都不起作用。TransactionClosedResizing, Moving...TransactionClosedDisplayNameComponentAddedComponentAdding

我还有一个问题,我尝试的示例项目是CustomFormsDesigner作为其他普通 Windows 窗体应用程序运行的,它显示了一个工具箱、一个 DesignSurface 和一个属性网格。我在运行它后做所有事情。但是你的情况呢?我的意思是,当您将控件拖放到 DesignSurface 上时,您是否仍处于 Visual Studio 窗口中的设计阶段?或在您自己的应用程序(作为设计器)窗口中?

我不得不说,这个问题对我来说太复杂了。谢谢你,我知道这种应用程序。

于 2013-06-09T00:29:55.617 回答
1

虽然我觉得这有点“hacky”,但我不一定知道它是错误的(如果它在技术上是“错误的”,请给我一些关于最佳实践的反馈!)它解决了手头的问题。

我最终做的是根据我阅读的 MSDN 文章扩展 ToolboxItem。

public class SurfaceToolboxItem : ToolboxItem
{
    private delegate void SetTextHandler(Control c, string text);
    public string ReportFieldName { get; set; }

    protected override IComponent[] CreateComponentsCore(IDesignerHost host)
    {
        var ctrl = (Label)host.CreateComponent(typeof(Label));
        var root = (Control) host.RootComponent;

        root.BeginInvoke(new SetTextHandler(SetText),
                         new object[] {ctrl, ReportFieldName});

        return new IComponent[]{ ctrl };
    }

    private void SetText(Control ctrl, string text)
    {
        ctrl.Text = text;
    }

}

一些明显的缺陷:

  • 此项目只会创建一个标签控件
  • 此项只会根据公共字符串属性设置所述标签控件的文本属性。

为了克服这些问题,可以将项目扩展为更像基本 ToolboxItem 的行为(实现接受 Type 参数的 ctor,允许传入属性名称/值的字典以在事后设置等)

此外,这破坏了我从工具箱到设计表面的拖放功能,这特别令人沮丧,因为原因并不太明显。问题出在我的工具箱服务实现的 DeserializeToolboxItem 方法中。

最初它看起来像这样:

ToolboxItem IToolboxService.DeserializeToolboxItem(object serializedObject)
{
   return (ToolboxItem) ((DataObject) serializedObject).GetData(typeof (ToolboxItem));
}

问题是由于对象是 SurfaceToolboxItem 类型,所以对 ToolboxItem 的强制转换返回 null,因此我将方法修改为如下所示:

ToolboxItem IToolboxService.DeserializeToolboxItem(object serializedObject)
{
   var data = (ToolboxItem) ((DataObject) serializedObject).GetData(typeof (ToolboxItem));

   return data ?? (ToolboxItem)((DataObject)serializedObject).GetData(typeof(SurfaceToolboxItem));
 }

因此支持我的扩展以及默认的 ToolboxItem。

于 2013-06-13T17:55:15.913 回答