简体   繁体   中英

C# Implementing Cut/Copy/Paste on Custom Form Designer

I am working on a custom form designer using the code in the this article . Everything is working fine except when Adding a functionality like Cut, Copy & Paste. The sample code provide a code for Deleting control which is working fine. But when I try the code below to Cut/Copy/paste, it's not working. Any idea?

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);
 }

Below is the code for 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();
        }
    }

From what I see,

It seems you are not adding the MenuCommands to the MenuCommands list object

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

        return false;
    }

In your code, you are checking if the MenuCommand already exists in the list of MenuCommands.

So I think when you initialise the list of commands, make sure to add that to the list before trying to call the invoke method

menuService.AddCommand(StandardCommands.Delete)

You can check https://docs.microsoft.com/en-us/dotnet/api/system.componentmodel.design.standardcommands?view=netframework-4.8 on how to add a StandardCommand to the menuCommands

I resolved my problem. It just need to add some serialization. like below:

_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);
}

See link for more details.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM