I've been playing with Windows Form Application for a half year, and now I found a very wired thing: The control created in Form Designer cannot be set with another instance in code.
Here is what I've done:
I create a Windows Form Application, the main form is Form1 class. And I drag a GroupBox control to Form1, then I add this code in Form_Load event:
private void Form1_Load(object sender, EventArgs e)
{
GroupBox gb = new GroupBox();
gb.Text = "gb in code";
groupBox1 = gb;
//groupBox1.Text = "set in code";
}
Normally, I thought it will give instance groupBox1 the new value of 'gb', which is another instance of GroupBox class, the the Text property is "gb in code". However, when I press F5, compile and run, the groupBox1 Text is still "groupBox1". And even if I uncomment the last line, the groupBox1 Text is not changed to "set in code".
I feel it's so wired. Is it because I created the groupBox1 instance in Form Designer? So I cannot revalue it in another partial of class?
I kinda need to revalue the control created in Form Designer, for my user controls.
Any help will be much appreciated. Thanks guys :)
--------------------EDIT---------------------
What I want to achieve is: I have two user controls: UC1 and UC2, and Now I'm creating another user control UC3, which contains UC1 and UC2. When I initiate UC3, I want to pass the instance of UC1 and UC2 to UC3, otherwise I have to pass all the property values of UC1 and UC2 to UC3. And I kinda need to use Designer for UC3, to re-size UC1 and UC2.
So in UC3, I drag my UC1 and UC2 to UC3 Designer, and I make a public property point to UC1 and UC2, like:
public UserControl param_UC1
{
get
{
return UC1;
}
set
{
UC1 = value;
}
}
But unfortunately, the UC1 is not set by param_UC1. Now I think I should not use designer, just add UC1 during the Load event.
Thanks a lot for your help :)
Your thinking is completely incorrect.
What you're doing here.. is creating a reference to an in-memory GroupBox instance. Then you're pointing your current reference at this new instance. That means both references are pointing at your in-memory GroupBox.. your GroupBox on your form is now completely unreferenced.
If you need to set properties on the control.. do so through the initial reference. Currently you're changing properties of your in-memory GroupBox. Your thinking here is completely wrong.. maybe you would benefit from telling us what you're trying to achieve so that we can help you achieve that goal.
Related
This might be kind of beginner question but I searched and didn't find any clear answer!
The main question is: How to inherit properties of a control (specially FlatStyle) from a base form which doesn't have that control in C#?
Details: I have Form1 inherited from baseForm. baseForm has a Panel and a Label control but no Button. In Form1 I added a button named Button1. How can I change the style of that Button through the baseFrom?
I don't want to create a custom control or redesign the button using rectangles or similar ways, but only change that property for all buttons in my application.
UPDATE: I want all of the buttons to be affected, whether they already exist or just added. Not matter in which -if any- container they are.
In baseForm, you could hook the ControlAdded event on the Panel where the Button is to be added, and style appropiately via code. This will work for every form inherited from baseForm.
For example (in baseForm)
public partial class BaseForm : Form
{
public BaseForm()
{
InitializeComponent();
// "myPanel" is the panel where the button will be added in inherited forms
myPanel.ControlAdded += myPanel_ControlAdded;
}
private void myPanel_ControlAdded(object sender, ControlEventArgs e)
{
var button = e.Control as Button;
if (button != null)
{
button.FlatStyle = FlatStyle.Flat;
button.ForeColor = Color.Red;
}
}
}
Just made a really quick test... it works even in design mode:
As an alternative, if you are going to use heavily styled buttons everywhere in your application, you may consider creating a custom control inheriting from Button, and assign the properties there, like:
public class FlatButton : System.Windows.Forms.Button
{
public FlatButton()
{
FlatStyle = FlatStyle.Flat;
}
}
After building, you will find it in the Toolbox (under "[Your Project's] components" tab), or you can cram it on your own control library (in a different solution) and add it permanently to the Toolbox in Visual Studio.
You would need to make use of Reflection
You can use a LINQ query to do this. This will query everything on the form that is type Button
var c = from controls in this.Controls.OfType<Button>()
select controls;
foreach(var control in c)
control.FlatStyle = FlatStyle.Flat;
In my C# application there is a main form with a panel main_panel. Whenever the user selects something in the menu, lets say "A", the main panel switches to the form A's panel (look at the code), A_panel.
Since A_panel covers every controls in form A, I can summon all of the controls of form A into main form.
if ((string)MainMenu.SelectedItem == "A")
{
FormA A = new FormA();
new_panel = A.Controls["A_panel"] as Panel;
}
this.main_panel.Controls.Clear();
this.main_panel.Controls.Add(new_panel);
My question is when user selects menu A again, I don't want to recreate FormA again by new FormA(). I did because when I add control to the main_panel, then the A_panel's ownership changes to main form so that it was possible to add the control to main_panel again.
So, how to change the ownership of A_panel to Form A again?
And how to solve my problem generally?
Any reason you can't use a UserControl and keep a reference to it on your form? That way you can just show/hide it when the user wants to change views. It would be much easier to extend and interact with. Here's a walk-through on MSDN to get you started.
It sounds like a UserControl would suit your needs better. Have one instance on FormA and another on your MainForm.
If, for some reason, you can't use user controls, you could at least extract the code outside the autogenerated designer file (which I assume is why you're using FormA at all).
As in:
FormA
public FormA()
{
var mainPanel = CreateMainPanel();
this.Controls.Add(mainPanel)
}
public Panel CreateMainPanel()
{
//...build up your control tree. Cut the code from the designer if necesssary
}
MainForm
FormA _A = new FormA();
public void HandleMainMenuClick(object sender, EventArgs e)
{
if ((string)MainMenu.SelectedItem == "A")
{
new_panel = _A.CreateMainPanel();
}
this.main_panel.Controls.Clear();
this.main_panel.Controls.Add(new_panel);
}
i'm new to windows application.can anybody help me.here is my doubt.im having one parent form and it has four menu items. when i click any of one menu item ,it should display another form within that parent form itself. how to do it?
Thanks in advance
According to details you ve provided it seems that you need to use MDI Forms concept in your app. It s very easy to learn and refer to the following links:
http://www.codeproject.com/KB/cs/mdiformstutorial.aspx
How to open a form within a form?
Just include the code in the 2nd link within your menuitem_Click event...
Hope this helps...
There are several ways you could do it.
One simple way for a newcomer is to add the form to the parent form in the designer. Set the visible Property to false (in the properties) so it will not be shown at first when your program is run.
Then you can set the visible property to true when you handle the menu item clicking.
There are code ways to do it too at runtime etc.
Hers an article with stuff about adding controls (and implicitly child forms) at runtime.
Inside your main form, add a panel and then use the below method to display the child form.
private void InitChildForm(Form childForm, Panel parent)
{
childForm.TopLevel = false;
childForm.Parent = parent;
childForm.Dock = DockStyle.Fill;
childForm.Show();
parent.Parent = this;
parent.Dock = DockStyle.Fill;
}
I'm building a small tabbed c# Form and I'd like each tab page to have some common features, notably, an OK button and an error message and to have a space for the specific form fields.
Has anyone else done something similar and how did you approach it?
This is easy to do without extending either TabControl/TabPage.
Define one UserControl, and put the common elements on it you want on every TabPage.
On the Form: go ahead and design the TabPage specific controls you want for each TabPage : make sure they are not going to visually overlap with the common controls once the UserControl has been added.
In the Form Load Event of your main Form do something like this :
// form scoped variable to hold a referece to the current UserControl
private UserControl1 currentUserControl;
private void Form1_Load(object sender, EventArgs e)
{
foreach(TabPage theTabPage in tabControl1.TabPages)
{
currentUserControl = new UserControl1();
theTabPage.Margin = new Padding(0);
theTabPage.Padding = new Padding(0);
theTabPage.Controls.Add(currentUserControl);
currentUserControl.Location = new Point(0,0);
currentUserControl.Dock = DockStyle.Fill;
currentUserControl.SendToBack();
}
}
Even though the 'SendToBack isn't really required here it is "insurance" that your UserControl with the 'Okay button and TextBox for an error message are placed behind the individual controls you have assigned to each TabPage.
Several ideas:
Keep the common controls outside the tabpanel;
Extend the TabPage/TabControl
Create a base UserControl with the common buttons and make usercontrols that inherit from it. Then place one inherited usercontrol per TabPage.
I have a simple user control with a text box and label in it. I created public properties to access the text in the textbox when I use the user control in another form.
My problem is the property is returning null value when I call it in the form. Am i missing anything?
My property is as follows::
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
}
public string rtnTxtMake
{
get
{
return txtMake.Text;
}
set
{
txtMake.Text = value;
}
}
}
and in the next forms button click event i call the property as follows
UserControl1 Usc = new UserControl1();
string Make = Usc.rtnTxtMake;
MessageBox.Show(Make)
UserControl1 Usc = new UserControl1();
string Make = Usc.rtnTxtMake;
If your user control has by default an empty textbox field, then it seems correct that the above two lines of code would return either null or String.Empty (check via String.IsNullOrEmpty), since you explicitly create a new instance of your user control.
I suppose what you really want is this:
You have inserted a user control into a form in the Designer. Let's call this user control instance ctlUser.
You have a button with a Click event handler. The last few lines of code in your question are from that handler method.
In the handler, you wouldn't create a new instance of your user control (Usc) but refer to the one that you previously inserted into your form, ctlUser. Then things should work as expected.
Your UserControl must be added to the Controls collection of a parent Form/Control before it can be properly initialized. Normally you would not write the code yourself that creates and adds the UserControl.
Instead, first build your project, then go to the Deisgner view of your main form and look at the Toolbox.
Your UserControl name (and an icon) should appear towards the top of the toolbox, and you can simply drag it to the main form. The Windows Forms designer will automatically generate the needed initialization code for you.
You should not create a new instance of your control in your button click event handler. Using the Designer approach to create your control you can simply access the existing instance of your control as follows:
public void button_Click(object sender, EventArgs e)
{
// myUserControl1 has already been created and initialized by the Deisgner generated code
// Note the name 'myUserControl1' is just an example, yours may be different.
string controlText=myUserControl1.rtnTxtMake;
// Or to change the UserControl textbox value
myUserControl1.rtnTxtMake="Testing";
}
What exactly to you mean when you say that the property is returning a null value? Is it actually null, or is your MessageBox simple showing empty?
I quickly duplicated your code and it behaves exactly as expected - the MessageBox shows, but it is empty because the default value of the Text property of the TextBox control is an empty string.
Also, the way you are approaching this is a little unusual.
Firstly, the line:
UserControl1 Usc = new UserControl1();
You do not generally need to instantiate a user control like this. Instead you can drag the control from the toolbox onto the design surface of your form. This will then take care of instantiating and initialising your control for you.
I think that this is actually your problem - when you include the line of code above, you are creating a new instance of the user control, and this is is no way realted to the user control that you have dragged onto the designer.
If you go to the designer view of your form and click on the user control, you should see a properties window somehere. If you do no, then either select it from the View menu, or press F4. In the list of properties, there should be one "Name" this is the programatic name generated for your user control. You can change this here if you want, but when you refer to this control in the rest of the form, this is what you must use.
Secondly, the next two lines:
string Make = Usc.rtnTxtMake;
MessageBox.Show(Make)
You can access the property rtnTxtMake directly. Unless you later need to access the Make string in the rest of your code, then directly accessing the property would usually be considered better style.
MessageBox.Show(userControl.rtnTxtMake);