I am attempting to make a complete custom TabControl.
So far my code works perfectly, however when I'm viewing my TabControl in the Visual Studio designer, I cannot add Controls into the TabPage Control which is inside of the TabControl. When attempted, it just places the control on top of the TabControl.
Unless you are adding controls to the TabPage via programming it by hand, that is, not using Visual Studio's Designer, using the TabControl is pointless.
PasteBin Link to my Control's Code
Here are images of the tab control with different tabs selected:
(source: gyazo.com)
(source: gyazo.com)
As you can see from the above images, the button is not placed into the tab page's control collection, as it floats above the tab control.
You can Use Tabcontrol from Design Toolbox in form and place the controls as you want.Then add the piece of code provided below to your code this will work.
Suppose you have custom class as Use this code write the Constructor as given below.
internal class MyCustomTabControl
{
public MyCustomTabControl(TabControl tabControlPassed)
: base()
{
this.tabcontrol = tabControlPassed;
}
TabControl tabcontrol;
}
In the main form Initialization call MyCustomTabControl initialization after InitializeComponent() method. Pass the this.tabControl1 while initializing Custom tabcontrol.
public partial class TabForm : Form
{
public TabForm()
{
InitializeComponent();
MyCustomTabControl customTab = new MyCustomTabControl(this.tabControl1);
}
}
:)
Related
I am trying to design some "standalone" tab-pages and later on, I want to add them dynamically to a tab-control in my main form. Visual Studio won't let me open the class extended with TabPage in the designer. Some idea?
using System;
using System.Windows.Forms;
namespace Test.View.Panels {
public class MainStatusTabPage : TabPage {
public MainStatusTabPage() {
}
}
}
When I right-click the class in the Solution Explorer and selecting "View Designer", I get the following message (the Designer doesn't show up):
To add components to your class, drag them from the Toolbox and use
the Properties window to set their properties. To create methods and
events for your class, switch to code view.
When I right-click the class in the Solution Explorer and selecting "View Designer", I get the following message (the Designer doesn't show up):
To add components to your class, drag them from the Toolbox and use the Properties window to set their properties. To create methods and events for your class, switch to code view.
This is normal behavior as a TabPage is just a container that holds other controls, nothing more. As #PanagiotisKanavos mentioned above:
A Tab Page is a container, not the actual content of the tab. In all examples that use complex content you'll see that the content is a custom component, eg a User control, that's added into the tab
With this in mind, you can just create a UserControl with all the other controls you would need and then add this new instance (UserControl) to the TabPage itself.
I know that getting the Form Designer to work is a ticklish business. Generics, x64, subtle problems with the project's XML... But perhaps someone can offer advice about my current problem, which is that a component I created that inherits from TabPage, when I try to view it in the designer shows up as a list of its controls, like this:
Thanks in advance.
You cannot make a TabPage as root of the designer, while you can do the same for a Panel or other container controls. The limitation is because, TabPage can only be hosted in TabControl, not even in the overlay control of the designer:
TabPage cannot be added to a
'System.Windows.Forms.Design.DesignerFrame+OverlayControl'. TabPages
can only be added to TabControls.
A control can be shown as root of the designer when the base class of the control has designer of type of DocumentDesigner. Form and UserControl are such controls which means when you create a new Form1:Form or new UserControl1:UserControl, since the base class derived from a designable control, then the class can be edited in the designer as root.
I believe you can handle your requirement by using UserControl, but for learning purpose (or as a workaround) if you want to make a control deriving from Panel designable, you can copy the following code in a code file:
public class MyControl: MyDesignableControl
{
}
[Designer(typeof(DocumentDesigner), typeof(IRootDesigner))]
public class MyDesignableControl : Panel
{
}
Then save it and then double click on it and you can see you can design it like a root control.
Then after you done with the design, change the Panel to TabPage.
Remarks on
DocumentDesigner
This designer is a root designer, meaning that it provides the
root-level design mode view for the associated document when it is
viewed in design mode.
You can associate a designer with a type using a
DesignerAttribute.
For an overview of customizing design time behavior, see Extending
Design-Time
Support.
I would like to know how I could possibly modulate my views in an application. Let me explain.
Instead of building my view and adding all the components in one screen. I want to say put each panel in its own class / form and then have a main form where I can add and remove these 'modular' panels.
Is this possible and how would I go about doing it?
In Windows Forms there is the concept of an empty component called UserControl, that can be freely designed and added at any time to another component or form container. UserControls are used very often in order to create flexible and exchangable UI. You can create a UserControl item in Visual Studio like this:
Name the new control:
After that you can design your UI control:
When your are done with the design, compile your project/solution and go to the form where you want to add your newly designed control. In the toolbar panel you will see your new UserControl, which can be added to the form with drag & drop (with the mouse):
You can create as many UserControls as you want and add/remove them to/from your form.
All of this steps can be done completely in the code. In order to create new view of this kind, you need to create a new class that inherits the predefined UserControl class:
public class EditorUserControl : UserControl
{
}
Every Control element has a ControlsCollection that holds/contains components of type Control that are drawn when the UI is shown. In order to add your new control to the main panel you need to add it to the controls collection:
public partial class EditorUserControl : UserControl
{
public EditorUserControl()
{
var button = new Button();
button.Text = "Import";
this.Controls.Add(button);
}
}
Note, that when adding components manually, you are responsible for sizing and position them. Predefined layout panels can help you here:
TableLayoutPanel - layout with cells
SplitPanel - horizontal or vertical predefined resizable panels
etc.
Now all that left is to add the new user control to the main form just like you added the UI elements to your own control:
var simpleEditor = new EditorUserControl();
simpleEditor.Dock = DockStyle.Fill;
this.Controls.Add(simpleEditor);
You can adjust the UI control settings through its predefined properties.
You can mix predefined containers and UserControls in order to achieve the desired UI:
There are a lot of good beginners tutorials for C# and VS and .NET:
Channel9 tutorials
MSDN Visual Studio UI tutorials
Composite UserControl tutorial
Developing with Windows Forms Documentation and Examples
This is definitely possible. I will use WinForms but there are similar ways in WPF such as frames.
In WinForms you can create a new User Control for each 'modular' panel which will automatically create .cs and .designer.cs files just like in a normal Form. You can then add logic and functionality to the panels as if they were forms themselves. All that would then remain is to add the logic to the form to load the default panel on startup and think of ways of how other panels can be brought into view (e.g. a next button or having a panel on each tab in a tab control). Showing a panel in a form (or any other user control for that matter) is achieved by creating an instance of your desired panel and adding it to you form/control's Controls property like so:
public Form1()
{
InitializeComponent();
MyPanel panel = new MyPanel();
this.Controls.Add(panel);
}
I'm trying to write a form theme class library to adjust the form layout in a simple way for any project I'll be working on.
This is basically an idea of what it should look like:
http://www.beaverdistrict.nl/form_layout.png
In essence, the plugin works as follows:
// form class, which inherits the plugin class
class FormToTheme : ThemedForm
{
public FormToTheme()
{
// some code here
}
}
// plugin class itself
class ThemedForm: Form
{
public ThemedForm()
{
// some code here
}
}
Basically I set the FormBorderStyle to None, and drew the layout by code.
But now, the controls that are added can be placed over the custom titlebar, which isn't possible in a normal form if you keep the default FormBorderStyle.
So I figured that I could work around this by automatically adding the controls to the content panel, instead of the usercontrol.
So what I tried to do was this:
private void ThemedForm_ControlAdded(Object sender, ControlEventArgs e)
{
// some simple code to set the control to the current theme I'm using
e.Control.BackColor = Color.FromArgb(66, 66, 66);
e.Control.ForeColor = Color.White;
// the code where I try to place the control in the contentPanel controls array,
// and remove it from it's parent's controls array.
if (e.Control.Name != contentPanel.Name)
{
e.Control.Parent.Controls.Remove(e.Control);
contentPanel.Controls.Add(e.Control);
}
}
But when I try to add a new control in the main form as well as in the visual editor, i get the following error:
child is not a child control of this parent
So my question is: is there a way to work around this error, and move the controls from the usercontrol to the content panel?
Note that I do want this to be automated in the ThemedForm class, instead of calling methods from the main form.
EDIT:
I tried this:
http://forums.asp.net/t/617980.aspx
But that will only cause visual studio to freeze, and then I need to restart.
I know that it is not really appropriate to answer ones own question, however the solution I came up with will take quite some explaining, which will be too much to add in my question with an edit.
So here we go:
Inside the inherited 'ThemedForm' class, I created a private variable, in order to be able to return the variable when the Controls property would be called:
private Controls controls = null;
I set the variable to null, because I need to pass variables to the class in the 'ThemedForm' class constructor. I will create a new instance of the class later on.
Then I created a class to replace the Controls property:
public class Controls
{
private Control contentPanel = null;
private ThemedForm themedform = null;
public Controls(ThemedForm form, Control panel)
{
contentPanel = panel;
themedform = form;
}
public void Add(Control control)
{
if (control != contentPanel)
{
contentPanel.Controls.Add(control);
}
else
{
themedform.Controls_Add(control);
}
}
public void Remove(Control control)
{
if (control != contentPanel)
{
contentPanel.Controls.Remove(control);
}
else
{
themedform.Controls_Remove(control);
}
}
}
I know this class holds far from all functionality of the original Controls property, but for now this will have to do, and if you like, you can add your own functionality.
As you can see in the Add and Remove methods in the Controls class, I try to determine wether the control that needs to be added is either the content panel I want to add the rest of the controls to, or any other control that needs to be added to the content panel.
If the control actually is the content panel, I add or remove it to or from the Controls property of the base class of the 'ThemedForm' class, which is a 'Form' class. Otherwise, I just add the control to the content panel's Controls property.
Then I added the Controls_Add and Controls_Remove methods to the 'ThemedForm' class, in order to be able to add or remove a control from the Controls property of the 'ThemedForm' base class.
public void Controls_Add(Control control)
{
base.Controls.Add(control);
}
public void Controls_Remove(Control control)
{
base.Controls.Remove(control);
}
They are quite self-explanatory.
In order to call the Controls.Add or the Controls.Remove methods from an external class, I needed to add a public property that hid the current Controls property, and returned the private variable that I assigned to the replacing class.
new public Controls Controls
{
get { return controls; }
}
And finally I created a new instance of the Controls class, passing the current 'ThemedForm' class, and the contentPanel control, in order to get it all to run.
_controls = new Controls(this, contentPanel);
After doing all this, I was able to 'redirect' any controls that were added to the UserControl (even inside the visual editor) to the content panel. This allowed me to use the Dock property of any control, and it would dock inside the content panel, instead of over my entire form.
This is still a little bit buggy, because inside the visual editor the docked controls still seem like they are docked over the entire form, but when running the application the result is as I wanted.
I really hope this helps anyone.
First off, I'm new to WPF and C# so maybe the issue I have is really easy to fix. But I'm kinda stuck at the moment.
Let me explain my problem.
I have a WPF Window and two usercontrols (Controls and ContentDisplayer).
The usercontrol Controls, wich contains some buttons, is added in the XAML of the Window.
Nothing special here.
Window.XAML
<nv:Controls/>
Now, what I want to do is when a user is pressing a button in Controls, ContentDisplayer needs to be added to the Scatterview I have in my Window.
I solved the problem by adding the buttons to the Window, and not using the usercontrol Controls. But this is not what I want.
Window.XAML.CS
private static void Button_ContactChanged(object sender, ContactEventArgs e)
{
object ob = Application.LoadComponent(new Uri(
"NVApril;component\\XAML\\ContentDisplayer.xaml",
System.UriKind.RelativeOrAbsolute));
//Set a unique name to the UserControl
string name = String.Format("userControl{0}",
SurfaceWindow1_Scatterview.Items.Count);
UserControl userControl = ob as UserControl;
userControl.Name = name;
//Add the new control to the Scatterview
SurfaceWindow1_Scatterview.Items.Add(userControl);
SurfaceWindow1_Scatterview.RegisterName(name, userControl);
}
So the real question is: How do I add a usercontrol to the Window by pressing a button in an other usercontrol?
Thanks,
Toner
At the top of the window xaml add
xmlns:d="clr-namespace:SomeNamespace.Usercontrols"
where you these exist already, you can choose the namespace of your control from the intellesence list.
Then where you want to place the control type:
<d:yourusercontrolhere params />
and your usercontrols can be added there.
Within Controls expose an event that is fired when you want to add a new control.
public event EventHandler AddControl;
private void RaiseAddControl()
{
if (AddControl!= null)
{
AddControl(this, EventArgs.Empty);
}
}
Now sink that event in your Window
yourControl.AddControl += ContactChanged
In your window, it sounds like you need to add the event to the instances of Controls.
<local:ContentDisplayer>
...
<nv:Controls AddControl="ContactChanged"/>
...
Then in your ContactChanged event handler you can instantiate a new Controls control and add it to whatever collection you're using like in your Button_ContactChanged event handler above.
Let me know if you need further clarification.
I have no idea what you are trying to do your example,
So you have a control defined thus:
public partial class somecontrolname : UserControl
With your corresponding Xaml file
All you need to do to add it in code to your window is firstly you need a LayoutRoot such as Grid control in the window then just
[mylayoutcontrol].Children.Add(new somecontrolname());
Maybe I got wrong idea what you are trying to do, your example code doesn't make much sense to me, looks like you are trying to load the xaml source file