Reputation: 2993
I have a c# WinForm application that I need to generate TabPages at runtime. Ideally, I would like to design these tabpages using VS designer, but it seems that I can't directly do that as I can't drag and drop it from the toolbox (is there another way?).
I have two generic tabpages that I will be using multiple times. One that contains a simple spreadsheet and a couple textboxes and another with a graph and a couple textboxes. These pages will eventually get more complicated. I'm looking for the best method of doing this. I am presently just creating custom classes for each tab page and setting it as a TabPage base class. For example:
public partial class SpreadsheetTabPage : TabPage{}
I read that user controls offer some form of an alternative, but I don't really understand the advantages of using it vs. my method.
So to be clear, I want to know what you think is the best approach to developing these custom tabpages and why. Please provide a basic code example if relevant. My method is not really causing too much problems, but I see adding things to these pages later on will be difficult, particularly without use of the designer.
Thanks for your help in advance!
Upvotes: 7
Views: 16102
Reputation: 83
I came across this thread with the same question in mind. After thinking about the problem I realized the solution was staring me in the face. It is actually pretty basic and elegant.
What I did was created a UserControl called TabPageLibrary. Accordingly I dragged a TabControl on it and Added Pages based on the set up I wanted. I then set the TabPage modifier to internal. When I needed a specific extended TabPage - I would simply call the TabPageLibrary class and grab the TabPage I need for a specific application. This gave me the ability to reuse a specific pre-configured TabPage throughout the winform application
private void PropertiesButton_Click(object sender, EventArgs e)
{
TabPageLibrary library = new TabPageLibrary();
TabPage propertyPage = library.PropertyPage;
this.tabControl.TabPages.Add(propertyPage);
}
This certainly solved my problem -- perhaps it will work for your application.
Upvotes: 6
Reputation: 1690
You can create your own TabControl designer, and implement the functionality you need at design time. Here is the code of the simplest version of such designer:
using System;
using System.Drawing;
using System.Collections;
using System.Windows.Forms;
using System.Windows.Forms.Design;
using System.ComponentModel.Design;
using CustomTabControlExample.TabControl;
namespace CustomTabControlExample.Design {
public class CustomTabControlDesigner :ParentControlDesigner {
DesignerVerbCollection fVerbs;
public override DesignerVerbCollection Verbs {
get {
if (fVerbs == null)
fVerbs = new DesignerVerbCollection(new DesignerVerb[] {
new DesignerVerb("Add Tab", OnAdd)
});
return fVerbs;
}
}
void OnAdd(object sender, EventArgs e) {
TabPage newPage = (TabPage)((IDesignerHost)GetService(typeof(IDesignerHost))).CreateComponent(
typeof(CustomTabPage));
newPage.Text = newPage.Name;
((System.Windows.Forms.TabControl)Component).TabPages.Add(newPage);
}
public override void InitializeNewComponent(IDictionary defaultValues) {
base.InitializeNewComponent(defaultValues);
for (int i = 0; i < 2; i++)
OnAdd(this, EventArgs.Empty);
}
protected override void WndProc(ref Message m) {
base.WndProc(ref m);
// Selection of tabs via mouse
if (m.Msg == 0x201/*WM_LBUTTONDOWN*/) {
System.Windows.Forms.TabControl control = (System.Windows.Forms.TabControl)Component;
int lParam = m.LParam.ToInt32();
Point hitPoint = new Point(lParam & 0xffff, lParam >> 0x10);
if (Control.FromHandle(m.HWnd) == null) // Navigation
if (hitPoint.X < 18 && control.SelectedIndex > 0) // Left
control.SelectedIndex--;
else control.SelectedIndex++; // Right
else // Header click
for (int i = 0; i < control.TabCount; i++)
if (control.GetTabRect(i).Contains(hitPoint)) {
control.SelectedIndex = i;
return;
}
}
}
protected override void OnDragDrop(DragEventArgs de) {
((IDropTarget)((System.Windows.Forms.TabControl)Component).SelectedTab).OnDragDrop(de);
}
protected override void OnDragEnter(DragEventArgs de) {
((IDropTarget)((System.Windows.Forms.TabControl)Component).SelectedTab).OnDragEnter(de);
}
protected override void OnDragLeave(EventArgs e) {
((IDropTarget)((System.Windows.Forms.TabControl)Component).SelectedTab).OnDragLeave(e);
}
protected override void OnDragOver(DragEventArgs de) {
((IDropTarget)((System.Windows.Forms.TabControl)Component).SelectedTab).OnDragOver(de);
}
}
}
This seems like a quite a complex way, but once you learn it, you will be impressed by powerful capabilites provided by Visual Studio. You can find a lot information in the MSDN. Here are described most common features: Enhancing Design-Time Support
Upvotes: 9
Reputation: 4348
If you make a user control that contains your tabcontrol you can see the designer and design it as you like, and you can add some additional code, and still can drag & drop it from toolbox to use it.
Note: you can't see you user control (neither your manually coded class) untill you Rebuild your project
Upvotes: 3