I have a class
public abstract class BaseFormClass : UserControl
and another class:
public class DerivedFormClass : BaseFormClass
if i open design view on baseformclass it show 3 components at the top.
but if i open derivedformclass, it does NOT show these 3 components, I have tried declaring
InitializeComponent virtual and overriding, but this made no difference.
Its annoying as if i run it then it displays fine, but i want it to work in designer so it easier to work with in future.
any ideas?
I have found out what works,
'both' class definitions need to extend the base class
so designer and general
public partial class BaseFormClass : UserControl
...
partial class DerivedFormClass: BaseFormClass
...
then the DerivedFormClass's designer will show the components from the BaseFormClass,
an alternative is to just define the baseformclass and then user that control in teh derived form class,
but this depends on what you need to implement.
Related
I have to work on a project on which there are several Form which have 80% of the code the same. So I try to create a generic class to make inheritate all my Forms of the UserControl class (the basic one) and my own class. But .Net doesn't support multi classs inheritance. So I create a middle class to do the inheritance chain like I can see on the net but I think I miss another step. Each class is in a different file for information.
The problem is I can't open anymore the designer for my initial Forms, because "Visual Studio cannot open a designer for the file because the class within it does not inherit from a class that can be visually designed".
Other information, I have a Mainwindow which inherite from "Form" and call one or another UserControl I design to show it.
What I had at the beginning :
namespace i2SIMDCProduction
{
public partial class MyForm1 : UserControl
{
public MyForm1(MyOwnClass myClass)
{
InitializeComponent();
this.myClass = myClass;
}
}
}
namespace i2SIMDCProduction
{
public partial class MyForm2 : UserControl
{
public MyForm2(MyOwnClass myClass)
{
InitializeComponent();
this.myClass = myClass;
}
}
}
What I have now :
namespace i2SIMDCProduction
{
public partial class MyForm1 : MyMiddleClass
{
public MyForm1(MyOwnClass myClass)
{
InitializeComponent();
this.myClass = myClass;
}
}
}
namespace i2SIMDCProduction
{
public partial class MyForm2 : MyMiddleClass
{
public MyForm2(MyOwnClass myClass)
{
InitializeComponent();
this.myClass = myClass;
}
}
}
namespace i2SIMDCProduction
{
public partial class MyMiddleClass : UserControl
{
public void MethodForAllChild()
{
}
}
}
Thank you in advance for any kind of help. I tried different things already (create a third class at the top of the file of my Forms for example, create empty constructor, ...) but nothing which works for now. The more frustrating is it is compiling and working but only the designer is KO.
If you want different forms to share the same visual controls on the screen then you set up inheritance between the forms.
Use the inherited form option in Visual Studio
For example, Form1 has a group box, with a label and two text boxes
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public void CommonMethod()
{
}
}
and Form2 inherits from From1 and adds a list box
public partial class Form2 : Form1
{
public Form2()
{
InitializeComponent();
}
public void SpecificMethod()
{
base.CommonMethod();
}
}
As you can see the controls from Form1 show up on Form2 also with a little icon to indicate that they are inherited.
If instead you just need to share code (like business logic) and not visual controls, then you create a separate class to hold the code with a link to the parent form, and then each form should contain an instance of this class.
What you want to do is a Model-View-Controler setup, where the Model is only data-related classes, View is only UI code, and the controller goes between the two doing the heavy lifting with processing user inputs and updating values.
The inheritance and designer in Windows Forms is a problem.
I have a Form with an splitter, two listboxes and some other controls. That form is used to translate (map) some items. You select one item at left, one at right and click button to match. They are the same item in different providers.
I have another provider that require some extra controls to do the translation. May be 90% or more of the code is the same, but I need some extra for this provider.
The options that I saw:
Add these extra controls (protected or public) to the Form, hidden by default and without use. In Form derived class, you use them. You haven't the designer in derived Form, but you don't need because controls are in base Form. The problem with this approach is that the designer part of inheritance of derived Form is in base Form. It's a nonsense. I don't recomend this option.
Don't use the designer in derived Form. Starting in the previous point, copy the designer code added for your derived Form into your derived Form and leave your base Form as at first stage, without nothing of derived Form. You don't use the designer but you can use it temporary, copy/paste and have a good inheritance... without the designer in derived Form. It's a good option if your derived Forms has few changes, few maintenance in the designer part.
You can "Add" some logic to your base Form to allow extensions. For example, below of the ListBox, I can add a Panel (hidden by default) and some methods like ShowLeftPanel/ShowRightPanel. By default, these panels aren't used, but in derived class I can add an UserControl in left panel and show it. And that UserControl show the properties that I need to show in the special provider. Add some virtual methods for listbox selection changed, to update the UserControl. In this way, your UserControl has designer and also the base Form. You only need add some "extension points" in your form (a Panel, a Splitter...) and give some methods to interact with this parts of the base Form. And this is ok with inheritance because is something generic, like Tag property in controls.
UPDATE
Check this solution and tell me about it. Make your Forms like this:
public partial class MyForm1 : UserControl, IMyUserControl
{
private readonly MyOwnClass myClass;
public MyForm1(MyOwnClass myClass, MyMiddleClass myMiddle)
{
InitializeComponent();
this.myClass = myClass;
this.MyMiddle = myMiddle;
}
public MyMiddleClass MyMiddle { get; }
}
In this way, all your panel's forms are IMyUserControl:
public class MyUserControl : IMyUserControl
{
public MyMiddleClass MyMiddle { get; }
}
So, having any of your panel's form, you can cast to IMyUserControl and get the related MyMiddleClass having access to methods like MethodForAllChild:
public class MyMiddleClass
{
public void MethodForAllChild()
{
}
}
In your main form, you may have some property or method that give you access to your UserControl. Create a method that give you the middle instance of the current UserControl:
private MyMiddleClass GetMyMiddle()
{
UserControl userControl = GetYourMainFormCurrentUserControl();
IMyUserControl myUserControl = userControl as IMyUserControl;
return myUserControl?.MyMiddle;
}
And use it in your main form when you need:
MyMiddleClass myMiddle = GetMyMiddle();
if (myMiddle != null)
{
myMiddle.MethodForAllChild();
}
In this way, you only need implement the interface and add a property in your forms/usercontrols. In the main form you can get this middleclass and the code to reuse is only in that class and shared in all places. You don't need copy/paste if you add or change something in the middle class.
UPDATE 2
I'm going to explain in other form how it works because the code is written above. The goal is having the code only in one place, without duplicate it.
You define an interface in a very similar way as a class but without implementation (this is not really true in lastest C# versions but we can suppose that is without code). C# don't allow multiple inheritance but you can derive from a class and implement as many interfaces as you want.
When we define IMyUserControl we are telling that every class that implements IMyUserControl, has a property MyMiddle. When MyForm1 implements IMyUserControl, if you don't add the MyMiddle property, you get a compiler error. The key with this solution is that add and implement this interface in each form is very easy: add IMyUserControl, the property and a parameter in the constructor to set the property.
So, all your forms implements now IMyUserControl. I don't know where are your forms but it's sure that you have a way to get access to your UserControl. Maybe a variable or an array in which you add your user controls. You are working with them, so you can access to your user controls. Well, if you have an UserControl instance, and you know that your UserControl implements IMyUserControl, you can cast your UserControl to IMyUserControl and after the cast, you have access to the interface, in this case, to the MyMiddle property.
And we put in MyMiddle all the code that you want to share.
If you add some code of your main form, where you work with your forms, I can help you with the code. I haven't more code than existing in my answer.
I was working on a WinForm, and for an unknow reason, I can't open it in design mode anymore, any (only that specific form). Is there anyway to tell Visual Studio 2013 that it's a WinForm and not a Class ?
You can "unload" the project, and then edit the .csproj file. Search for your .cs file, and insert a SubType node... <Compile Include="Scraper.cs"><SubType>Component</SubType></Compile>. Save the .csproj and Reload your project.
For me I had a class defined before the partial class, i.e.:
public class MyClass { ... }
public partial class MyForm : Form { ... }
Defining MyClass after MyForm fixed the problem.
Same happens to me, when I did some base class for my forms and manually change to it in generated forms.
Solution was to add
[System.ComponentModel.DesignerCategory("Form")]
attribute to base class definition.
P.S.: same way around, you can use
[System.ComponentModel.DesignerCategory("Code")]
if you want some own derived control to never open in designer, like if it is a user conhtrol.
Right-click on your file in Solution Explorer, "Open with.." and reselect the designer in the list. Maybe? Or maybe your Designer.cs file has an issue or was somehow corrupted as mentionned by the replier above.
If you remove the Form inheritance after your form class you experience the behaviour described
public partial class MyMainForm : Form
{
}
here, if you remove the inheritance from the base Form class Visual Studio shows your form code instead of the designer when you double click on the form name in the Solution Explorer
Make sure your namespaces match on the form class StateRuleDetailTriggerForm.cs and its designer class StateRuleDetailTriggerForm.Designer.cs.
it's any way to inherit form from baseForm, f.e:
i have Baseform with menu and some button. Now I want to use it in my second form, but i would not copy-paste, but only:
public partial class Form1 : BaseForm
and now i have some problems, because compilator send me bugs:
Message 1 The designer could not be shown for this file because none
of the classes within it can be designed. The designer inspected the
following classes in the file:
dziedziczony --- The base class '_10widokow.BaseForm' could not be
loaded. Ensure the assembly has been referenced and that all projects
have been built.
Those errors probably due to your BaseForm either not being referenced, or you have other problems outside of the scope of the question.
Controls on a form are added by the InitialiazeComponents method generated by the Form graphical editor. You don't need to inherit to bring in a basic set of controls, but simply copy the generated code out to a common location.
Then call in the constructor of the forms in which you want the base controls.
Okay, so some of you may be familiar with the Krypton Toolkit by Component Factory. If not, check it out here.
Anyways, you can change the form style completely using this toolkit by opening the designer code for your form and changing this line:
Inherits System.Windows.Forms.Form
To this:
Inherits ComponentFactory.Krypton.Toolkit.KryptonForm
That is Visual Basic though. I would like to achieve this using C#.
In the form's code-behind file instead of this:
public partial class Form1 : Form
type this:
public partial class Form1 : ComponentFactory.Krypton.Toolkit.KryptonForm
Note, that this isn't a changing of form's style, this is changing of base class. To open code-behind, you should press F7 in designer by default.
in C# you have 2 cs files for your form.
Say your form is called Form1, you'll have to go to the file Form1.cs and change this line:
public partial class Form1 : Form
to
public partial class Form1 : ComponentFactory.Krypton.Toolkit.KryptonForm
that should do the work
I'm making some controls which all have to share the same look and some common behavior, although they are meant for different kind of inputs. So I made a BaseClass which inherit from UserControl, and all my controls inherit from BaseClass.
However, if i add controls for BaseClass in the designer, such as a TableLayoutPanel, i can't access them when I'm designing the inherited classes. I see the TableLayoutPanel, but even though he is "protected", i can't modify it or put controls in it through the designer. I've no trouble accesing it by code, but i don't want to lose the ability to use the designer.
Right now, i simply removed all controls from BaseClass, added the layout and all the common controls in each of the inherited class, then use references to manipulate them inside BaseClass. But that doesn't satisfy me at all. Is there a way to make the designer work with inherited protected member controls ?
Environment : C#, .NET 3.5, Visual Studio 2008
EDIT to answer SLaks's suggestion. I tried setting a property, and although I'm not used to use them it doesn't seem to work. Here is the code i tried :
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
}
public TableLayoutPanel TableLayoutPanel1
{
get { return tableLayoutPanel1;}
set { tableLayoutPanel1 = value;}
}
}
public partial class UserControl2 : UserControl1
{
public UserControl2()
{
InitializeComponent();
}
}
When you try to access from the inherited control with the designer to the TableLayoutPanel declared in the base control, you're using a feature in WinForms called "Visual Inheritance".
Unfortunately TableLayoutPanel doesn't support visual inheritance:
http://msdn.microsoft.com/en-us/library/ms171689%28VS.80%29.aspx
That's why the TableLayoutPanel appears blocked in the inherited controls.
Try adding this attribute to the definition of the panel (this may or may not help):
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
You have to design the base controls on their own. Changes are reflected in the designer after you successfully rebuild the controls project. If you make the members public you can edit them but the changes won't persist.
Try making a ParentControlDesigner for your control, overriding InternalControlDesigner, and returning (designerHost.GetDesigner(tableLayoutPanel) as ControlDesigner). designerHost is (IDesignerHost) component.Site.GetService(typeof(IDesignerHost)).
I vaguely remember solving a similar problem by putting the base class it its own DLL and building it first. I've had a rummage but I can't find the project. Sorry.