C# 在自定义窗体设计器上实现剪切/复制/粘贴



我正在使用本文中的代码开发自定义表单设计器。一切都运行正常,除了添加剪切,复制和粘贴等功能。示例代码提供了用于删除控件的代码,该代码工作正常。但是当我尝试下面的代码剪切/复制/粘贴时,它不起作用。知道吗?

private ServiceContainer serviceContainer = null;
private MenuCommandService menuService = null;
private void Initialize()
{
IDesignerHost host;
Form form;
IRootDesigner rootDesigner;
Control view;
// Initialise service container and designer host
serviceContainer = new ServiceContainer();
serviceContainer.AddService(typeof(INameCreationService), new NameCreationService());
serviceContainer.AddService(typeof(IUIService), new UIService(this));
host = new DesignerHost(serviceContainer);
// Add toolbox service
serviceContainer.AddService(typeof(IToolboxService), lstToolbox);
lstToolbox.designPanel = pnlViewHost;
PopulateToolbox(lstToolbox);
// Add menu command service
menuService = new MenuCommandService();
serviceContainer.AddService(typeof(IMenuCommandService), menuService);
// Start the designer host off with a Form to design
form = (Form)host.CreateComponent(typeof(Form));
form.TopLevel = false;
form.Text = "Form1";
// Get the root designer for the form and add its design view to this form
rootDesigner = (IRootDesigner)host.GetDesigner(form);
view = (Control)rootDesigner.GetView(ViewTechnology.WindowsForms);
view.Dock = DockStyle.Fill;
pnlViewHost.Controls.Add(view);
// Subscribe to the selectionchanged event and activate the designer
ISelectionService s = (ISelectionService)serviceContainer.GetService(typeof(ISelectionService));
s.SelectionChanged += new EventHandler(OnSelectionChanged);
host.Activate();
}
private void PopulateToolbox(IToolboxService toolbox)
{
toolbox.AddToolboxItem(new ToolboxItem(typeof(Button)));
toolbox.AddToolboxItem(new ToolboxItem(typeof(ListView)));
toolbox.AddToolboxItem(new ToolboxItem(typeof(TreeView)));
toolbox.AddToolboxItem(new ToolboxItem(typeof(TextBox)));
toolbox.AddToolboxItem(new ToolboxItem(typeof(Label)));
toolbox.AddToolboxItem(new ToolboxItem(typeof(TabControl)));
toolbox.AddToolboxItem(new ToolboxItem(typeof(OpenFileDialog)));
toolbox.AddToolboxItem(new ToolboxItem(typeof(CheckBox)));
toolbox.AddToolboxItem(new ToolboxItem(typeof(ComboBox)));
toolbox.AddToolboxItem(new ToolboxItem(typeof(GroupBox)));
toolbox.AddToolboxItem(new ToolboxItem(typeof(ImageList)));
toolbox.AddToolboxItem(new ToolboxItem(typeof(Panel)));
toolbox.AddToolboxItem(new ToolboxItem(typeof(ProgressBar)));
toolbox.AddToolboxItem(new ToolboxItem(typeof(ToolBar)));
toolbox.AddToolboxItem(new ToolboxItem(typeof(ToolTip)));
toolbox.AddToolboxItem(new ToolboxItem(typeof(StatusBar)));
}
private void OnSelectionChanged(object sender, System.EventArgs e)
{
ISelectionService s = (ISelectionService)serviceContainer.GetService(typeof(ISelectionService));
object[] selection;
if (s.SelectionCount == 0)
propertyGrid.SelectedObject = null;
else
{
selection = new object[s.SelectionCount];
s.GetSelectedComponents().CopyTo(selection, 0);
propertyGrid.SelectedObjects = selection;
}
if (s.PrimarySelection == null)
lblSelectedComponent.Text = "";
else
{
IComponent component = (IComponent)s.PrimarySelection;
lblSelectedComponent.Text = component.Site.Name + " (" + component.GetType().Name + ")";
}
}
private void mnuDelete_Click(object sender, System.EventArgs e)
{
menuService.GlobalInvoke(StandardCommands.Delete);
}
private void menuItem2_Click(object sender, EventArgs e)
{
menuService.GlobalInvoke(StandardCommands.Cut);
}
private void menuItem4_Click(object sender, EventArgs e)
{
menuService.GlobalInvoke(StandardCommands.Paste);
}
private void menuItem3_Click(object sender, EventArgs e)
{
menuService.GlobalInvoke(StandardCommands.Copy);
}

以下是MenuCommandService的代码

internal class MenuCommandService : IMenuCommandService
{
ArrayList menuCommands = null;
public MenuCommandService()
{
menuCommands = new ArrayList();
}
public void AddCommand(System.ComponentModel.Design.MenuCommand command)
{
menuCommands.Add(command);
}
public void AddVerb(System.ComponentModel.Design.DesignerVerb verb)
{
// No implementation
}
public System.ComponentModel.Design.MenuCommand FindCommand(System.ComponentModel.Design.CommandID commandID)
{
return null;
}
public bool GlobalInvoke(System.ComponentModel.Design.CommandID commandID)
{
foreach(MenuCommand command in menuCommands)
{
if (command.CommandID == commandID)
{
command.Invoke();
break;
}
}
return false;
}
public void RemoveCommand(System.ComponentModel.Design.MenuCommand command)
{
menuCommands.Remove(command);
}
public void RemoveVerb(System.ComponentModel.Design.DesignerVerb verb)
{
// No implementation
}
public void ShowContextMenu(System.ComponentModel.Design.CommandID menuID, int x, int y)
{
// No implementation
}
public System.ComponentModel.Design.DesignerVerbCollection Verbs
{
get
{
return new DesignerVerbCollection();
}
}

据我所知,

似乎您没有将菜单命令添加到菜单命令列表对象

public bool GlobalInvoke(System.ComponentModel.Design.CommandID commandID)
{
foreach(MenuCommand command in menuCommands)
{
if (command.CommandID == commandID)
{
command.Invoke();
break;
}
}
return false;
}

在您的代码中,您正在检查菜单命令列表中是否已存在菜单命令。

所以我认为当您初始化命令列表时,请确保在尝试调用 invoke 方法之前将其添加到列表中

menuService.AddCommand(StandardCommands.Delete)

您可以查看有关如何将标准命令添加到菜单命令 https://learn.microsoft.com/en-us/dotnet/api/system.componentmodel.design.standardcommands?view=netframework-4.8

我解决了我的问题。它只需要添加一些序列化。如下所示:

_codeDomComponentSerializationService = new CodeDomComponentSerializationService(serviceContainer);
if (_codeDomComponentSerializationService != null)
{
serviceContainer.RemoveService(typeof(ComponentSerializationService), false);
serviceContainer.AddService(typeof(ComponentSerializationService), _codeDomComponentSerializationService);
}
_designerSerializationService = new 
DesignerSerializationServiceImpl(serviceContainer);
if (_designerSerializationService != null)
{ 
serviceContainer.RemoveService(typeof(IDesignerSerializationService), false);
serviceContainer.AddService(typeof(IDesignerSerializationService), _designerSerializationService);
}

有关更多详细信息,请参阅链接。

最新更新