I have 2 forms that inherit a control from the class below:
public class AInbox: Form
{
public FlowLayoutPanel InboxItems;
}
The forms inherits as such:
public partial class Inbox : AInbox
{
...
}
In the Designer.cs file i commented out the original "InboxItems" control declaration and everything compiles and runs fine... except the GUI designer. When i open the Designer I get the error "The variable 'InboxItems' is either undeclared or was never assigned."
Is there any way to use this inheritance and still have the designer work?
I'd recommend against inheriting a form with generated code (like you're doing with Inbox).
If you want the child class (Inbox) to add additional controls, I wouldn't use the designer directly on the child class, because I don't think the visual studio form designer will play nicely when half of the form was designed in the parent class. If you need to reuse certain parts of your form in a different form, you might want to consider moving that part of the form to a separate user control. You can use the designer on this user control and later put the user control in the forms.
If you just need to have the same form, keep an instance of the form in your other class. Move your logic away from your form (view) and in your other class (controller).
Related
Currently I'm creating a really big project in Visual Studio 2012, where there are some common settings for each form ("Cancel" and "Save" buttons, Methods that change in every form but have the same name, font sizes and types, form color etc.) it will save me a lot of time if I could do all the design a single windows form and when I edit or modify it, have the changes reflected in the other forms as well.
Let's say I need 10 forms, to create them I would choose this default format and have my menu and basic objects already placed and designed; then after 10 forms I decided to move a button a bit, but don't want to go to every form and move it; just change it in the original format, refresh and all my forms will have that button in the new location.
I used Templates as recommended by Can one set the default properties for new WinForms created in Visual Studio?. But I still have the issue that if I change something in the template it won't refresh in every other form created with the template to that point.
I've already thought of changing the InitializeComponent in the WinForm default format, but this is not recommended and I wouldn't want any errors from this later on.
Any ideas?
Thanks in advance
Inheritance will work for your solution.
Create "base" form with all "common" controls
Create new "derived" form and change form to inherit from your "base" form.
If you have some common logic in base form, which need to be "overridden" in derived forms - put it to the virtual method
// Base form
protected virtual void Close()
{
// Base logic
}
private void CloseButton_Click(object sender, EventArgs e)
{
Close();
}
// In derived form - just override "Close" method
protected override void Close()
{
// custom logic - will be executed when "Close" button clicked
}
In base form leave empty space for custom controls. Because you will not be able access baseform controls through designer in derived form.
Another approach - Model-View-ViewModel(MVVM)
- Introduce own UserControl with common controls(view) which have property - instance of ViewModel.(Viewmodel will contains behaviour logic and possibility to change "base" settings.)
- Add this user control to all "derived" forms and set UserControl.ViewModelProperty to instance which will represent logic for this particular form.
Without knowing "full" context of your goals - difficult to suggest more, but I am pretty sure you can build maintainable relations between forms, which can share common logic and view.
No, there is nothing you can do. Once you use a template to create a project or a file, it becomes a one-off. You have to edit it manually, or use a text editor that is powerful enough to employ a find and replace with pattern matching and capture group insertion.
I'm trying to make a WindowsFormApplication in Visual Studio 2015 and need some help.
I've been trying to search for the answer on internet but can find out how to do the following:
I have two windows (solutions?). I open the second window with a button in the first one with this code:
this.Hide();
intermec prodinter = new intermec();
prodinter.ShowDialog();
My question is:
How can i "include" the second window (like "include" in PHP) instead of close the first window and then open the next one, like it does now?
A Form is just another Control. Think of it as a Container (because it holds other Controls).
A User Control can also hold more than one Control. There are ways you can display a Window inside another Window in a WinForms app, but the desired effect is not always guaranteed. So it would be best to place all of your controls (for "page 1", for example) in a User Control called "Page1", and then, when appropriate, add that User Control to the Form, and set its Dock property to Fill.
And when it's time to show a different "page", Hide(); "Page1", and Show(); "Page2".
I think you are talking about form inheritance:
Just create a form, lets call it as frmBase. And add some controls onto frmBase which you want to have on other forms as well.
Create other form, lets call it as frmDerived.
In the code behind of frmDerived, just do the following:
// derive the frmDerived form from frmBase
public partial class frmDerived : frmBase
{
public frmDerived()
{
InitializeComponent();
}
}
And then just check the frmDerived form design, it should include everything from frmBase.
And you may want to make the access modifier of some controls of frmBase to Public as required to access them on frmDerived.
I hope this will help you. :)
I have a lot of different UserControls and would like to maintain consistent UI settings (mainly colors and fonts). My first try was this:
public class UISettings
{
//...
public void SetupUserControl(ref UserControl ctrl)
{
ctrl.BackColor = this.BackColor;
}
}
to be called in every control like this:
settings.SetupUserControl(ref this);
As this is read-only it cannot be passed by ref argument so this does not work. What are other options to keep consistent UI without manually changing properties for every item?
Inheritance! If you have a form or control that will constantly be using the same styles and you want to set that as your base, just create your own user controls that inherit from a form/control. By default all of your forms will inherit from "Form". Instead of inheriting from the default form, create a new user control that inherits from Form, and then have that as your base class.
CustomForm : Form // Your custom form.
Form1 : CustomForm // Inherit from it.
...the same works for components. If you want a button to have the same styles across the board, create a user control and have it inherit from the button control -- then use the custom control.
Whenever you want to make a change to your base styles, or any settings, simply change your custom controls settings -- your new forms/controls will automatically be updated!
Do the same thing. Don't pass it by ref. UserControl is a reference object already, so there's no need to pass it into your method using the ref keyword.
You may also want to consider a recursive method that will find all the UserControls on the form and pass it into your method.
How about a base class which provides such settings?
Two answers:
You don't need ref, controls are objects are reference types. Just drop it.
Create a Base UserControl and derive your controls form that base. You can still do that, just edit the class definitions of the controls. For new controls you can follow the Wizard.
A tip: setup the styling in the baseControl. Then make sure the derived controls don't override, the best way to do that is scanning the *.Designer.cs files and remove all settings that you know should come from the base.
An application I'm working will have a number of forms with a lot of shared functionality. For instance, each form will have a DataGridView, many of the same buttons, much of the same UI code and so on.
I'd like to implement this by creating a base version of this common form, subclass it for all these very-similar-but-not-quite-the-same child forms, and tack on whatever additional controls and features I need for each of them.
I've already figured out that it helps to make the base form's controls protected because this allows things like anchoring to work propertly. However, I have yet to find a way to automatically make the derived forms the same size as the base form.
Experience tells me there should be a simple way to do this. While it's not much of a problem to just type in the required size by hand for every derived form right after creating it, I'd prefer to make everything as clean, simple, and automatic as possible.
I find it interesting that your derived forms do not automatically inherit the size from their base form, because this should work without you having to do anything about it.
Suspected cause of your problem:
I suspect your problem results from the fact that you're using Visual Studio's Forms Designer to edit the forms. Whenever you've edited a form, Windows Forms Designer generates the required code in the InitializeComponent method of your forms. Among all the generated code are assignments that set a form's size, even if it is identical to the base form's size. Therefore you might have to manually comment out those assignments if you want your derived form to have the same size as the base form, even when you change the base form's size after creating the derived forms. (However, I don't know if that might lead to further problems with the controls' positioning & layouting.)
// Code to be commented out in your derived form's InitializeComponent method:
this.AutoScaleDimensions = new System.Drawing.SizeF(...);
this.ClientSize = new System.Drawing.Size(...);
Once these lines are commented out, the size as set in your base form's InitializeComponent will be used for the derived form.
A workaround solution:
You can do the following so that you don't have to manually comment-out designer-generated code every time you've edited a form:
Create an form derived from your base form; let's call it FrozenBaseForm. You will derive all other forms from this class instead of directly from the base form. Now, in this "intermediate" class, you define a new property ClientSize:
public class FrozenBaseForm : BaseForm
{
new public SizeF ClientSize
{
get { return base.ClientSize; }
set { }
}
}
This will cause all assignments to ClientSize to have no effect at all and therefore preserve the size from the base form. This feels like a hack to tell the truth, but it seems to work. You might have to hide the Size property in the same way btw.
As said, derive your forms from FrozenBaseForm instead of from BaseForm directly:
public class DerivedForm1 : FrozenBaseForm { ... }
public class DerivedForm2 : FrozenBaseForm { ... }
...
Another option (last resort if all else fails):
As a last resort, you could simply forget about the Forms Designer and just define the derived forms manually in the code editor (though I personally would not want to do this):
public class DerivedForm : BaseForm
{
public DerivedForm()
{
// make all necessary changes to the base form:
...
}
}
public partial class derivedForm : baseForm
{
public derivedForm()
{
InitializeComponent();
this.Width = base.Width;
this.Height = base.Height;
}
}
Why not make the BaseForm set the size of itself?
public partial class BaseForm : Form
{
public BaseForm()
{
InitializeComponent();
// you could hardcode these or retrieve these values from a
// config file or something
this.Width = 640;
this.Height = 468;
}
}
Wouldn't this do what you want?
I have a Form and a UserControl. The UserControl has a menu, and the form has a tabstrip (General, Food, Vitamins etc).
In the UserControl, I have the following code: (Form name is frmForm, the tab names in the form are tabGeneral,tabFood, tabVitamins)
frmForm fm=new frmForm();
fm.tabMain.Selected=tabVitamins;
I call these line from the UserControl to capture the tab to get selected on the form, but it does not select the vitamins tab.
Where am I going wrong? I have access specifier as Protected Internal for tabs in the form.
Please advice.
Thanks,
Karthick
When you write new frmForm(), you're creating a completely new instance of frmForm, which is then discarded.
To get the frmForm instance that holds your control, call the FindForm() method and cast to frmForm.
For example:
frmForm myForm = FindForm() as frmForm;
if(myForm != null)
myForm.tabMain.SelectedTab = myForm.tabVitamins;
If the control is on some other form, this code won't do anything.
By the way, Hungarian notation is frowned upon in .Net.
Your form should probably be named something like MainForm.
SLaks has correctly pointed out your fundamental error, and given you a valid example of a way, via a call to the method 'FindForm, to get the Form the UserControl is sited on.
It may be valuable to you to keep in mind that a UserControl (and all Controls) also has a 'Parent property, but, of course, a UserControl could be placed inside another Control on a Form (like your UserControl could be inside a Panel on the Form) : in that case the UserControl's Parent would be the control it's inside on the Form (like, a Panel), not the Form itself, but 'FindForm will do the right thing to get you the Form it's on.
However you are calling a Method every time you use 'FindForm, and "best practice" suggests that what you want to do is to "inject" a reference to the Form into the UserControl at run-time so that it can always access its Form property easily, without calling a 'Method.
In your example, on a practical level, this (calling the Method) may make almost no difference in performance, but, imho, as you get to a place with WinForms and .NET where you might have a UserControl that will need access to its Parent Form very frequently, this will pay off, and it's a better way to structure your code in the long run, for maintenance.
Wes showed you one way you can "embed" (inject) the UserControl's hosting Form : using an overloaded constructor for the UserControl. But that requires you to modify the Designer.cs file in standard WinForms, and I strongly advise you against that, even though it will work. Particularly if you are just "getting your feet on the ground" in .NET, I strongly advise you against modifying it, or anything having to do with the Form's constructor and its internal call to : InitializeComponent();
Also, as you progress with WinForms you are going to meet many situations where you are going to want instances of "objects" (a Control, a Form, an instance of a Class) to contain references to other instances of "objects.
If you can understand and use one simple use of "injection" here, you are going to make progress to make yourself ready to handle more complex .Net programming in the future.
Another way is to put a Public Property in the UserControl that can be set in code from the MainForm. In the UserControl something like :
private frmForm ParentForm;
public frmForm UCParentForm
{
set { ParentForm = value; }
}
So then in your main form's code, perhaps in the Load event like this :
private void frmForm_Load(object sender, EventArgs e)
{
TheUserControl.UCParentForm = this;
}
or when you need to, you set the UserControl's 'ParentForm property once. So you have eliminated using the method 'FindForm().
In this case, if you only want access to a specific control on the UserControl's Parent Form, like a TabControl, you might consider that you want to make the Property you set of type TabControl, rather than Form : the same coding technique shown above can be used in the UserControl :
private TabControl mainFormTabControl;
public TabControl MainFormTabControl
{
set { mainFormTabControl = value; }
}
imho, it is when you are creating UserControls dynamically at run-time, using an overloaded constructor, as Wes suggests, is the best strategy. And using overloaded constructors has many, many others uses in .NET that you'll get into.
good luck !
You should not be creating a new frmForm() inside the user control. You could pass a reference to the frmForm to the user control.
In your user control constructor try something like this.
private frmForm fm;
public YourUserControl(frmForm fm)
{
this.fm = fm;
}
Then you could use.
fm.tabMain.Selected=tabVitamins;
Does that help?