• 0

[C#] Adding buttons/tabs to a ToolStrip/TabControl in my user control


Question

I have this custom user control that has a ToolStrip and a TabControl and I'm adding my own designer to the user control so at design-time I can automate some actions. The smart tag panel as a verb called "Insert New Page", this verb is going to add a button the ToolStrip and a Tab to the TabControl every time you click on it.

Well, part of this works, the other part, doesn't. When you click the "Insert New Page" verb, the button will be added to the ToolStrip and the tab will be added to the TabControl, also, if you open "Form1.Designer.cs", you will see that the code for the button/tab, was generated.

However, if you run the application after adding one or more buttons/tabs, the Form will be pratically empty. Only the user control will be there, but not the added button/page. And the code is on the "Form1.Designer.cs" file.

I'm pasting below the most important code about this (I think) but I am also attaching a "DesignerTest.zip" file which is a complete solution with the above description of my control and what I'm tyring to do so you can test for yourself without having to recreate everything.

Just launch the solution in VS, select the only control on the Form, click "Insert New Page" and F5 the application and see what happens...

internal class MyUCDesigner : ControlDesigner
{
	private DesignerActionListCollection alColletion;

	public override DesignerActionListCollection ActionLists
	{
		get
		{
			if (alColletion == null)
			{
				alColletion = new DesignerActionListCollection();
				alColletion.Add(new MyUCDesignerActionList((MyUserControl)Control));
			}

			return alColletion;
		}
	}
}

internal class MyUCDesignerActionList : DesignerActionList
{
	private MyUserControl myUserControl;

	public MyUCDesignerActionList(MyUserControl control) : base(control)
	{
		myUserControl = control;
	}

	private void InsertNewPage()
	{
		IComponentChangeService ICCS = (IComponentChangeService)GetService(typeof(IComponentChangeService));
		IDesignerHost IDH = (IDesignerHost)GetService(typeof(IDesignerHost));
		ToolStripButton tsButton;
		TabPage tPage;

		DesignerTransaction dTransaction = IDH.CreateTransaction("Insert New Page");

		tsButton = (ToolStripButton)IDH.CreateComponent(typeof(ToolStripButton));
		tPage = (TabPage)IDH.CreateComponent(typeof(TabPage));

		ICCS.OnComponentChanging(myUserControl, null);

		tsButton.Image = Properties.Resources.DefaultButton_Large;
		tsButton.ImageAlign = ContentAlignment.BottomCenter;
		tsButton.Text = tsButton.Name;
		tsButton.TextAlign = ContentAlignment.BottomCenter;
		tsButton.TextImageRelation = TextImageRelation.ImageAboveText;

		tPage.Text = tPage.Name;

		myUserControl.toolStrip.Items.Add(tsButton);
		myUserControl.tabControl.Controls.Add(tPage);

		ICCS.OnComponentChanged(myUserControl, null, null, null);
		dTransaction.Commit();
	}
}

DesignerTest.zipFetching info...

3 answers to this question

Recommended Posts

  • 0

I have made some new findings but haven't yet found a final solution for this. The above code and stuff is all good (I think) but probably missing something...

I mean, let's say you add my control to a form, open the smart tag panel and click "Insert new page", you will then have a button and a tab added to the ToolStrip/TabControl and if you open the "Form1.Designer.cs" file you will see the code there... You will also see the code for myUserControl1 like this:

// 
// myUserControl1
// 
this.myUserControl1.Dock = System.Windows.Forms.DockStyle.Fill;
this.myUserControl1.Location = new System.Drawing.Point(0, 0);
this.myUserControl1.Name = "myUserControl1";
this.myUserControl1.Size = new System.Drawing.Size(236, 189);
this.myUserControl1.TabIndex = 0;

But it's missing 2 lines, which are these:

this.myUserControl1.tabControl.Controls.Add(this.tabPage1);
this.myUserControl1.toolStrip.Items.Add(this.toolStripButton1);

If those 2 lines were in the code, it would work... The "Insert new page" smart tag panel verb adds the necessary code for the each added ToolStrip/TabControl ToolStripButton/TabPage, but does not add the necessary code to add those controls to the ToolStrip/TabControl.

So, how do I make that happen in design time?

PS: For the above to work, I had to change both the ToolStrip and TabControl controls in my custom user control to public.

  • 0

Solved. The solution was something like this:

[DesignerSerializationVisibility( DesignerSerializationVisibility.Content)]
[Browsable(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
public System.Windows.Forms.TabControl.TabPageCollection Pages
{
  get { return this.tabControl.TabPages; }

}

[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
[Browsable(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
public ToolStripItemCollection Buttons
{
  get { return this.toolStrip.Items; }
}

This worked as I wanted, however, there's a tiny little problem...

I added the code and then replaced:

this.myUserControl1.tabControl.Controls.Add(this.tabPage1);

this.myUserControl1.toolStrip.Items.Add(this.toolStripButton1);

By:

myUserControl.Buttons.Add(tsButton);

myUserControl.Pages..Add(tPage);

Then, let's say I test the designer implementation, open the smart tag panel and click "Insert new page", well, it works fine and if I undo, it also works. BUT, it doesn't work if I press redo.

Code after "Insert new page":

//
// myUserControl1
//
this.myUserControl1.Buttons.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.toolStripButton1});
this.myUserControl1.Dock = System.Windows.Forms.DockStyle.Fill;
this.myUserControl1.Location = new System.Drawing.Point(0, 0);
this.myUserControl1.Name = "myUserControl1";
this.myUserControl1.Size = new System.Drawing.Size(236, 189);
this.myUserControl1.TabIndex = 0;
//
// toolStripButton1
//
this.toolStripButton1.Image = ((System.Drawing.Image)(resources.GetObject("toolStripButton1.Image
this.toolStripButton1.ImageAlign = System.Drawing.ContentAlignment.BottomCenter;
this.toolStripButton1.Name = "toolStripButton1";
this.toolStripButton1.Size = new System.Drawing.Size(98, 51);
this.toolStripButton1.Text = "toolStripButton1";
this.toolStripButton1.TextAlign = System.Drawing.ContentAlignment.BottomCenter;
this.toolStripButton1.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageAboveText;

Code after "undo":

//
// myUserControl1
//
this.myUserControl1.Dock = System.Windows.Forms.DockStyle.Fill;
this.myUserControl1.Location = new System.Drawing.Point(0, 0);
this.myUserControl1.Name = "myUserControl1";
this.myUserControl1.Size = new System.Drawing.Size(236, 189);
this.myUserControl1.TabIndex = 0;

Code after "redo":

//
// myUserControl1
//
this.myUserControl1.Buttons.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.toolStripButton1});
this.myUserControl1.Dock = System.Windows.Forms.DockStyle.Fill;
this.myUserControl1.Location = new System.Drawing.Point(0, 0);
this.myUserControl1.Name = "myUserControl1";
this.myUserControl1.Size = new System.Drawing.Size(236, 189);
this.myUserControl1.TabIndex = 0;
//
// toolStripButton1
//
this.toolStripButton1.Name = "toolStripButton1";
this.toolStripButton1.Size = new System.Drawing.Size(23, 22);

PS: The variable declarations and the new() instantiations are created/deleted just fine with the undo/redo.

PS2: This code only shows the toolStripButton1 for example purposes.

So, if anyone knows how to fix this "redo" problem, it would be very helpful!

This topic is now closed to further replies.
  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Posts

    • OBS Studio 31.1.0 RC1 by Razvan Serea OBS Studio is software designed for capturing, compositing, encoding, recording, and streaming video content, efficiently. It is the re-write of the widely used Open Broadcaster Software, to allow even more features and multi-platform support. OBS Studio supports multiple sources, including media files, games, web pages, application windows, webcams, your desktop, microphone and more. OBS Studio Features: High performance real time video/audio capturing and mixing, with unlimited scenes you can switch between seamlessly via custom transitions. Live streaming to Twitch, YouTube, Periscope, Mixer, GoodGame, DailyMotion, Hitbox, VK and any other RTMP server Filters for video sources such as image masking, color correction, chroma/color keying, and more. x264, H.264 and AAC for your live streams and video recordings Intel Quick Sync Video (QSV) and NVIDIA NVENC support Intuitive audio mixer with per-source filters such as noise gate, noise suppression, and gain. Take full control with VST plugin support. GPU-based game capture for high performance game streaming Unlimited number of scenes and sources Number of different and customizable transitions for when you switch between scenes Hotkeys for almost any action such as start or stop your stream or recording, push-to-talk, fast mute of any audio source, show or hide any video source, switch between scenes,and much more Live preview of any changes on your scenes and sources using Studio Mode before pushing them to your stream where your viewers will see those changes DirectShow capture device support (webcams, capture cards, etc) Powerful and easy to use configuration options. Add new Sources, duplicate existing ones, and adjust their properties effortlessly. Streamlined Settings panel for quickly configuring your broadcasts and recordings. Switch between different profiles with ease. Light and dark themes available to fit your environment. …and many other features. For free. At all. OBS Studio 31.1.0 RC1 changelog: Fixed an issue where a Browser Source or Browser Dock would crash OBS Studio on macOS 13 or older [jcm93/PatTheMav/RytoEX] Fixed an issue where browser error pages could not scroll [WizardCM] Fixed an issue on macOS where menu items would launch unintended actions when OBS was set to certain languages [gxalpha] Fixed an issue in Beta 1-2 where the group icon in the Sources list was not positioned correctly in the System theme [shiina424] Fixed an issue in Beta 2 where the preview zoom button tooltip translations were incorrect [shiina424] Download: OBS Studio 31.1.0 RC1 | Portable | ARM64 | ~200.0 MB (Open Source) View: OBS Studio Homepage | Other Operating Systems | Screenshot Get alerted to all of our Software updates on Twitter at @NeowinSoftware
    • Nice little improvement One improvement I would like to see. Being able to use a voice commands in Firefox "Firefox, 2FA (enter a 2FA code)". "Firefox, Close all tabs right" "Firefox, Pin tab" "Firefox, Bookmarks (name of Bookmark to open a Bookmark)" "Firefox, Settings, X" among others.
    • Microsoft Defender XDR gets TITAN-powered Security Copilot recommendations by Paul Hill Guided Response, a Copilot-powered capability in Microsoft Defender XDR that guides analysts through step-by-step investigation and response flows, is getting a big upgrade with the introduction of TITAN recommendations. With TITAN, Microsoft wants to give security analysts real-time, threat-intel-driven recommendations so they can better prepare against attacks, before they even happen. TITAN is an adaptive threat intelligence graph that uses data from first and third-party telemetry and employs guilt-by-association techniques to warn analysts about unknown IP addresses that could pose a threat, due to their association with known malicious addresses. The primary benefit of TITAN is that security analysts get faster warnings about potential threats before they even have a chance to cause a problem. TITAN is an enhancement of Security Copilot Guided Response, rather than a replacement to it. With this extra tool, security analysts will be able to better keep up with evolving threats. Understanding TITAN's AI-powered threat intelligence The Redmond giant said that TITAN “represents a new wave of innovation” built upon its threat intelligence capabilities that introduces a real-time, adaptive threat intelligence graph. It takes telemetry from first and third-party sources such as Microsoft Defender for Threat Intelligence, Microsoft Defender for Experts, and customer feedback. The graph uses guilt-by-association techniques to mark unknown devices as threats, if they’re associated with known malicious entities. This gives security analysts a window of opportunity to take action and prevent harm. To identify potential threats, Microsoft uses a semi-supervised label propagation technique that assigns reputation scores to nodes based on the score of their neighbors. These reputation scores allow Microsoft’s unified security operation platform to implement containment and remediation actions via attack disruption. Practical impact and future outlook The new TITAN suggestion now appears within Guided Response as triage and containment recommendations. When a suspicious IP is detected, a Guided Response recommendation is automatically generated. These can help security analysts deal with various threats including IP addresses, IP ranges, and email senders. Microsoft said in early testing its TITAN recommendations have shown good results. TITAN boosted Guided Response triage accuracy by 8%, it reduced the time needed to investigate and respond to incidents, and its explainable recommendations gave analysts more confidence in the actions they take. As threats become more sophisticated, Microsoft’s TITAN will help to tackle threats before they even become an issue.
    • China wants the tech... if they were to invade, TSMC would destroy it's fabs and other critical information first. Plus, you can bet they have backups stored NOT in Taiwan.
    • Malware website host in China in 3….2…1
  • Recent Achievements

    • Enthusiast
      Motoman26 went up a rank
      Enthusiast
    • Mentor
      M. Murcek went up a rank
      Mentor
    • Explorer
      treker_ed went up a rank
      Explorer
    • Apprentice
      CHUNWEI went up a rank
      Apprentice
    • Veteran
      1337ish went up a rank
      Veteran
  • Popular Contributors

    1. 1
      +primortal
      674
    2. 2
      ATLien_0
      267
    3. 3
      +FloatingFatMan
      176
    4. 4
      Michael Scrip
      174
    5. 5
      Steven P.
      139
  • Tell a friend

    Love Neowin? Tell a friend!