I am trying to specify the parent MDI form when showing a form in c#
All the examples suggest just using
FormVariable.Parent = this;
this works ok assuming you want the form to be opened from the parent window all the time.
I want to be able to open a form and set the Parent form to my MDI Parent form by specifying the name.
in VB.net I have used
Me.MdiParent = TheNameOfMyParentForm
When I try anything similar in c#
this.MdiParent = CruxMDI();
I get
'Crux.CruxMDI' is a 'type' but is used like a 'variable'
Form.MdiParent has to reference a concrete instance. So, maybe it would be a good idea to implement a Singleton pattern (you probably don't want to allow multiple parent windows either way, do you?) in your Parent container, so that you can reference it from wherever you need to. Then you'll just type:
this.MdiParent = CruxMDI.Instance;
If you want to add such behavior automatically and it needs to happen in many Forms in your application, you may consider an option when you'd create a custom base class inheriting from Form. That way you specify this once and then you just need to be sure to inherit your new Forms from this baseclass instead of a default Form.
Either way, you need to have some kind of mechanism to reference the instance of your MDI container.
Related
The majority of my forms for my project include an OK and Cancel button. (always positioned at the bottom right of the form). Currently I have a base class that inherits from System.Windows.Forms which contains an OK and Cancel button. All forms that use this then inherit from this base form class. Is there a better way of doing this that takes localization into consideration?
I would use MDI Child Forms for this. Parent Form Can contain OK/Cancel button where as you would have your child form in MDI container.
For More help visit
https://msdn.microsoft.com/en-us/library/aa984329(v=vs.71).aspx
You could just create a single form that has an empty panel or table layout, where you dynamically load the desired user control. It is basically the composition over inheritance principle.
public partial class MyFormWithButtons : Form
{
public MyFormWithButtons(UserControl control)
{
InitializeComponent();
control.Dock = DockStyle.Fill;
myPanel.Controls.Add(control);
}
}
Doing form inheritance is very useful in many levels:
Make a base form, and name it for ex: FrmBase.
Add the Ok, Cancel Buttons to it and set the Anchor property for both to Bottom.
Set the Buttons "Modifiers" property to "Internal", this way you can access these buttons from inherited forms:
Make as many forms as you want and make each inherit from the FrmBase ex: Form1 : FrmBase
now you can access the buttons from this from, using the properties.
Hope this being useful for you.
In c# winforms, I am having a problem whereby this block of code will create two variables that point to the same form instead of two different instances of the form:
Form formA = new LoginForm();
Form formB = formA;
formB.Close();
When formB is closed, both forms are closed. I am trying to avoid this, however I cannot find any solution such as formB = new Form(formA);
In my real solution, there are extra controls added to the first form (formA), and some additional data stored in the fields of the form. This is why I need to duplicate the first form
Any help is much appreciated!
If you want two forms, create two forms - two independent objects - by calling the constructor twice:
Form formA = new LoginForm();
Form formB = new LoginForm();
Now they're independent objects. Note that there's nothing winforms specific about this - it's the same for all classes.
EDIT: If you want to create a clone of the original form, you still need to create a new object - and each of the controls within the form would need to be cloned as well (a control can't have two parents). Cloning is a tricky business to get into, and I'd try to avoid it here if possible. Instead, I would try to effectively replay the same original actions which added the controls or set the data in the original form.
You haven't said much about what information is within your form, but if it's complex data, you probably want to isolate that from the form, encapsulating it in its own class... then you can decide whether you want a deep or shallow clone of that object when you create the second form.
There's not a single statement to do what you're asking.
You can create the second form, then copy the controls from the first to the second form, maybe using Controls.CopyTo (I'm not sure about CopyTo).
To handle the data, you can make a class that contains all the data you need to use, and copy clone of that class to the new form. Then you can manually populate some fields on the new form.
Currently I have a C# program with a windows form and then a user control template put onto the form. The user control template is really just used as a placeholder. I have a series of other controls which inherit from this user control template.
Each of those controls have navigation buttons like 'Continue' and 'Back' on them and each control knows which control needs to be loaded next. However what I need to figure out is an easier way to have variables that are global to these controls.
The only workaround I have is that I pass the form to each control when they are loaded and use variables inside of the form to read and write to. What would be the proper way to have each of these user control screens be built off of a base control which contained objects all of the controls could get to?
Sorry for the rambling nature of the post but I've been thinking about this problem all morning.
Here is some of the code:
Most of what I have written was based on hiding and showing the user controls so that content in the controls wouldn't be lost during navigation. I won't be needing to do that as eventually it will be loading the fields of data from a database.
Code for initially loading control from form click:
conTemplate1.Controls.Clear();
conInbound Inbound = new conInbound(this);
Inbound.Dock = DockStyle.Fill;
Inbound.Anchor = (AnchorStyles.Left | AnchorStyles.Top);
conTemplate1.Controls.Add(Inbound);
Code for Continue button inside of one of the controls:
if ((Parent.Controls.Count - 1) <= Parent.Controls.IndexOf(this))
{
UserControl nextControl = new conPartialClear();
nextControl.Dock = DockStyle.Fill;
Parent.Controls.Add(nextControl);
this.Hide();
Parent.Controls[Parent.Controls.IndexOf(this) + 1].Show();
}
else
{
this.Hide();
Parent.Controls[Parent.Controls.IndexOf(this) + 1].Show();
}
The best-practice for communicating from a control to a parent is to use events, and for communicating from a parent to a control is to call methods.
However, if you don't want to or can't follow this practice, here's what I would recommend.
Each UserControl has a ParentForm property that returns the Form that contains the control. If you know that the UserControl will always be attached to MyParentForm, you just cast the ParentForm and then you can access all public controls, methods, etc.
Here's what I mean:
public class conTemplate
{
public MyParentForm MyParentForm
{
get
{
return (MyParentForm)this.ParentForm;
}
}
}
This way, you can easily access any public members of MyParentForm. Your conInbound class could have code such as this.MyParentForm.GlobalSettings.etc..., and could even have access to any public controls.
I'm not totally sure I understand your problem. It sounds like you want the user control to "do something" with it's parent form. If that's the case, you may want to consider adding events to the UC and then handle them on the form itself.
Basically, for your UC's "continue", you'll have an event that's fired when it's pressed. You'll want to handle that in your form. I'm not real sure about the syntax from memory, or I'd work something out for you code-wise. But I think that's the route you'll want to take. Think of your UC like any other windows form control. If you add a button to your form, you assign it it's event method. Do the same with the UC.
I found this and thought it may be helpful. Scroll down to where it talks about UC's and events.
http://www.akadia.com/services/dotnet_user_controls.html
Hope this helps.
EDIT after new info from OP.
You could declare a global variable inside the UC of type yourForm and then set that variable to the ParentForm at run-time, if I'm understanding you correctly.
So, inside your UC Class, you could do:
private parentFormInstance;
then inside the constructor of the UC, you could set it as such:
parentFormInstance = this.ParentForm; (or whatever the property name is).
This allows you at design-time to use:
parentFormInstance.DoSomething();
without the compiler yelling at you.
Just basic advice, but if you can go back and make it easier on yourself, even if it takes some additional time re-working things, it'd be worth it. It may save you time in the long run.
If I add a component class to my project containing some common controls, how can I display an instance of it in a panel in my main form?
I use this to create an instance of my class:
Component test = new Component1();
where Component1 is the name of my Component class
Then how could I do something like:
panel1.Controls.Add(test); ?
Or is there a way to do this without using Panels?
You are using the wrong class. A Component cannot be a child of a panel or a form, it doesn't have a visual presentation. The missing Handle property is the important one.
You need a Control. Derive your class directly from Control or from one of the built-in control classes (Button, Label, etc). You'd do the latter if you want to customize their behavior and make it re-usable.
Then how could I do something like: panel1.Controls.Add(test); ?
This is the correct way.
Or is there a way to do this without using Panels?
You could add your control to something other than a panel; for instance, to the form itself: Controls.Add(test).
I am currently working in a small windows forms project in C# using Visual studio 2008.
I have added a custom class to the project, but in this class I am unable to access the forms controls (like listbox, textbox, buttons ) in order to programmatically change their properties.
The class file has using system.windows.forms included and all files are in the same namespace.
Surprisingly, I am also unable to access the controls in the form1 class itself, unless I create a method in the class and then intellisense pops up the names of the various controls.
in the custom class however, intellisense does not show the names of the controls at all.
Appreciate if someone coudl shed some light on why this could be happening.
Thanks
Encapsulation means your separate class shouldn't be talking directly to the controls. You should, instead, expose properties and methods on your (outer) Control - for example:
public string TitleText {
get {return titleLbl.Text;}
set {titleLbl.Text = value;}
}
For more complex operations it may be preferable to use a method; properties are fine for simple read/write for discreet values.
This provides various advantages:
you can, if required, abstract the details to an interface (or similar)
you can change the implementation (for example, use the Form's Text for the title) without changing the calling code
it is just... nicer ;-p
Your class needs a reference to the form for this to work. The reason for this is that the form is not a static class so you can have multiple instances of it.
The best way of giving it the reference would probably be to pass it in the classes constructor. Then the class would have a reference to the form and could use that reference to change the controls.
An alternative option that you could use if you are 100% sure that you will have only one instance of your form open is to add a public static property to the forms class that returns the instance of the form. That property would then be available to be used in your other class.
Also, make sure that your controls are public, or better add public methods to your form that can be used to manipulate the controls indirectly.
The controls in Form1 will be private
partial class Form1
{
//elided other good stuff
private System.Windows.Forms.Button button1;
}
So no, you can't access this directly from another class.
You could make it public as #abatishchev suggests (but that would be a really bad idea).
A better plan would be to use properties as #Marc Gravell suggests.
You would still need to pass a reference to the form to the class that you wish to have consume the properties though (as pointed out by #Rune Grimstad).
You are trying to write a class in your application that directly asks the UI for data. This isn't usually considered a very good idea. The class should be entirely concerned with it's own purpose. You should design properties or events for the specific bits of data that the class needs access to and not necessarily pass it the entire form, maybe just the values that it needs to work with or change.
Take a look at how this could be implemented using the MVP pattern (sample code): Implementing MVC with Windows Forms
UPDATE: The code in the class you mention should in fact be part of the form's presenter, which has a reference to the form (through the IView interface). That is how you should be designing your UI code, not by directly accessing other Form's private parts.