我正在使用DesignSurface类,我遇到了令人沮丧的问题,我似乎无法弄明白。我正在从我的工具箱拖动项目并将它们放到我的表单上没有问题,但我想修改这些项目的属性,因为它们被放置在DesignSurface上。因此,例如,如果我将标签拖到DesignSurface上,我可能会更改控件的BackColor的值。我知道ToolboxItem暴露了CreateComponents(),它接受一个可选的属性参数,但这是由较低级别的API调用的,我没有看到在何处或如何覆盖它,所以我可以提供自己的值。有没有人有任何想法?谢谢!
答案 0 :(得分: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
上拖放控件时,它仍然不受TransactionClosed
中代码的影响,我必须执行类似Resizing, Moving...
控件的操作,然后TransactionClosed
}事件被引发,它显示DisplayName
确定。我没有发现任何其他更好的事件,最合适的事件应该是ComponentAdded
或ComponentAdding
,但它们都不起作用。
我还有一个问题,我尝试的示例项目是CustomFormsDesigner
,它运行为其他常规Windows窗体应用程序,它显示了一个工具箱,一个DesignSurface和一个属性网格。运行之后我做了一切。但你的情况怎么样?我的意思是当你将控件拖放到DesignSurface上时,你仍处于Visual Studio窗口的设计时间?或者在您自己的应用程序(作为设计器)窗口中?
我不得不说,这个问题对我来说太复杂了。谢谢你,我知道这种应用。
答案 1 :(得分:0)
虽然我觉得这有点“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(实现ctor接受Type参数,允许传入属性名称/值的字典以在事后设置等)< / p>
此外,这使我的拖放功能从我的工具箱破坏到设计界面,这特别令人沮丧,因为它并不是太明显的原因。问题出在我的Toolbox Service实现的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。