Is there any good way in Windows Forms Designer to have an array (or other collection) of similar components defined? You can check "GenerateMember", which will give you a unique named member in code to reference, but what if I want that generated member to be one of a list of some sort, so that I can iterate through them easily? The only way I can think of is to create a new list on load, and the manually add all the already-generated members to that list, which is tedious and redundant. I thought about editing the code that generates these components, but it's inside that auto-generated "Do not modify" section, and I'm afraid any change I make there will be overwritten any time I make other changes to the form. Does the Form Designer just not have this functionality?
If I understand your question correctly, you can simply cast "this" (the form) to a "Control", and then examine it's "ControlCollection" property- a collection containing the form's controls. Eg.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
var myControlList = ((Control)this).Controls;
}
}
Unless I am missing something...
You could put them inside a Panel and then iterate through its controls.
Related
I'm almost done doing a Connect4 game with VS2012 using WinForms. Everything is working well but I wanted to bring the options for the user on a dedicated Start Menu window. On that menu I have two comboBoxes I need to take the text from to use them as a value for two variables in my other form (the game window). I also have one New Game button that should call a method from my other form if that's possible (basically, I made an "Initialization()" method in my game form and I'd like it to be launched when I click the "New Game" button on the other form).
I only found tutorials that show how to do very basic things from one form to an other (such as labeling texts) but I I didn't find an answer to my specific problem.
I used this in my main form to instantiate the menu form
public FormMenu myMenu;
myMenu = new FormMenu();
What I want to do is that I could do something like this in the other form :
amountOfRows = Int32.Parse(myMenu.comboBoxRows.Text);
amountOfColumns = Int32.Parse(myMenu.comboBoxColumns.Text);
Any idea how I could do that?
I would love to see some example code so I can help see where your confusion lies. WinForms requires the other form to be instantiated.
OtherForm form = new OtherForm();
Once the form is instantiated you should be able to run code from it.
EDIT:
Based on your implementation I would suggest making public methods within FormMenu that return these int values.
public int ReturnRows()
{
return Int32.Parse(myMenu.comboBoxRows.Text);
}
public int ReturnColumns()
{
return Int32.Parse(myMenu.comboBoxColumns.Text);
}
Then from the other form in which myMenu is instantiated you can call myMenu.ReturnRows() and myMenu.ReturnColumns()
The easiest way would be to store a reference to your form in the menue as a variable. (you already named it myMenu)
Then you should create the property/properties you need in the form an add a setter for the values. (see example here)
Last you update the form fields with
myMenu.property = newvalue;
That`s all about it
I have code that dynamically loads (and destroys) user controls of different types onto a form as they are needed. The user control uses properties from its parent to load certain values into controls such as textboxes and check boxes. The issue is that in the line:
activeControl = new userControl1(params...);
my constructor is obviously going to try loading fields that don't exist yet (they belong to the parent form) since it hasn't been added to the parent form until after userControl1 is created.
I tried solving this using the ParentChanged event of the user control so it waits until its parent is set before loading fields. The problem here is when I destroy userControl1 and create a userControl2, the parent changes and it tries to load the fields from the null ParentForm (the exact problem I had originally.
Is there a preferred way to tackle this? Clearly, I could just add something like
if(this.ParentForm == null) { return; }
to the ParentChanged event or something along those lines. But this feels neither elegant nor safe. Am I overlooking some event or preferred way to accomplish this?
While it is not necessarily bad to check for null references and divert the code accordingly (e.g. not try to reference a missing object), the better approach here is to decouple your UserControl classes from their parents.
That is, these UserControl classes should not have any awareness of their parent form types at all. To do otherwise is to negate one of the major benefits of OOP: code reuse. With your current design, even if you get it to work without crashing, you can't ever use these UserControl objects except in the context of this specific parent form type.
You may think today that that's okay, that you'll never want to use them in any other context. But the future is hard to predict. You may decide, for example, that you want a variation on the parent form that should still use these same UserControl objects.
What you should be doing is exposing the UserControl state via public properties, and then allow the parent form to initialize those as necessary.
Here's a very simple example (I'm omitting the Designer-created code…I assume that you can infer from the field names what I mean):
partial class UserControl1 : UserControl
{
/* ... */
public bool IsMyFlagChecked
{
get { return checkBox1.Checked; }
set { checkBox1.Checked = value; }
}
/* ... */
}
partial class ParentForm : Form
{
/* ... */
private void SomeMethodThatAddsUserControl1()
{
UserControl1 uc1 = new UserControl1;
uc1.IsMyFlagChecked =
this.SomeParentFormPropertyUserControl1UsedToReferenceDirectly;
// other initialization for uc1...
Controls.Add(uc1);
}
/* ... */
}
(Note that without a good, minimal, complete code example that illustrates your question, I can't provide a more detailed code example than the above. If this doesn't seem to address your question, please edit it so that it provides more detail, including a better code example).
I have a form and I have some buttons doing stuff.
When I press buttons the windows form controls, like textboxes or group-boxes, buttons appear and disappear and change place on my form, for it is a dynamic form :)
However, what I'd like to do is have a button ( BACK ) that will get my form to the state it was before an action of a button, putting back the controls in the place and state they were before action.
I thought of a C class MyState() that will have something like an array of Form1.
I will be saving the form state in that array and when I'll press the back button to get from array that "copy" of the Form state and maybe an index for indexing states.
I have no idea how to implement this, unfortunately. :|
Can anyone show me the right way to do this?
class Mystate
{
private Form1 [] state;
public Mystate(int n)
{
this.state = new Form1[n];
}
public Form1 this[int index]
{
get
{
return state[index];
}
set
{
this.state[index] = value;
}
}
}
Sounds like you want an high level undo/redo feature for your forms.
Here is a framework for such things: http://www.codeproject.com/Articles/10576/An-Undo-Redo-Buffer-Framework
Here is an answer that is close but not exactly the same as your question (The pattern implimented is the same though): How to implement good and efficient undo/redo functionality for a TextBox
MementoPattern: http://www.codeproject.com/Articles/18025/Generic-Memento-Pattern-for-Undo-Redo-in-C
Nothing like this is built-in. You have to do this on your own.
I'd do it like this: First, define precisely what state you want to save. Example:
Control.Bounds
Control.Text
Checkbox.IsChecked
NumericUpDown.Value
...
Now we know exactly what needs to be saved.
Seconds, we need a way to create a snapshot of the current state of the form and recursively for all controls. You can implement this using reflection so that everything will be automatic no matter how many controls you have.
Third, you need to be able to apply a snapshot to an instance of Form. This is the opposite process of (2). This also can be done using reflection.
Suppose I create a window form Form.cs. It has some controls(label1, label2, button1, button1 etc.). I also create a new window form New_Form.cs under Form.cs. Now I want to access label1, label2, button1 in New_Form.cs. How can I do this?
I don't want to be offensive, but I think that using control from another form is not a good design.
In my oppinion it is not good to couple one class (in this question form1) to the inner implementation of another class (controls of `form2´. If you, for some reason, have to change the inner design (e.g. showing the data with a different control) of that class, you have to change the other class too. That makes coding (and of course error searching) quite difficult.
If there is a need to exchange data between two classes, I would prefer using publioc Properties for that. In the inner design you can attach them to a control, but then this "coupling" stays in the same class)
Although this can be bad design, you can access properties in another Form by making them public and then accessing them like this:
Form1 frm = new Form1();
Form1.button1.Visible = false;
Also here is an msdn page pertaining to your question
http://msdn.microsoft.com/en-us/library/f6525896%28v=vs.90%29.aspx
You can access the required properties by setting them as public properties in your Parent form. Not sure as why you would want the button, if you want some thing to be executed for the click then you should encapsulate the logic into separate methods and them make the call.
If you have fewer details to pass then make constructors for the new form which would accept those values
ChildForm child = new ChildForm([label1], [label2])
or
ChildForm child = new ChildForm([parent form reference]) // so you could access require components
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?