User control in windows forms application - c#

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);

Related

Winform - SetFocus to textbox inside usercontrol on TabControl

Winform application
Multiple tabs
on the tabs are replicated Usercontrol
When clicking on a particular tab, I would like to setfocus to a textbox within the usercontrol. I would like to this if possible from within the tabControl_SelectedIndexChanged event.
ex:
textbox name = txtOne
txtOne resides within UserControlA
UserControlA resides within tabControl.SelectedTab.Text = "Tab2"
When I click Tab2 I'd like Focus to be set to txtone.
I've tried: (and many other things!)
UserControlA.Controls["txtone"].SelectAll(); - returns object reference not set to an instance of an object
Thanks!
Because txtone is not an immediate child of UserControlA, UserControlA.Controls["txtone"] will return null.
You can either dig your way down the control hierarchy with control names (UserControlA.Controls["fameFD"].Controls["txtone"]) or simply expose txtone as a public field or property in your UserControl class. The latter would look something like this:
public TextBox TxtOne {
get
{
return txtone;
}
}
Then you could refer to the textbox from external code like this:
UserControlA.TxtOne.SelectAll();

Triggering WinForm_Load() with a User Control nested in a Split Container

I'm currently working on a "Settings" screen for a project and want to implement a view similar to that found in Visual Studio, where there is a TreeView with a list of options and clicking on one of these options will load a UserControl in an adjacent panel in the same form. I am using a SplitContainer to group these two controls.
I thought that the Load event for the User Control would be triggered when it was displayed in the panel, but this is not the case. I also tried to trigger the Enter event but it still did not work so I tried to call a function when the form was initialized using the following method.
ViewSecurity newViewSecurity = new ViewSecurity(Globals._connectionString);
// This creates a new instance of the ViewSecurity form from within the TreeView.
And this is the code in the initializing function for the User Control
public ViewSecurity(string _cString)
{
InitializeComponent();
connectionString = _cString;
MessageBox.Show("Test");
populateData();
}
This method does not work either - the MessageBox does not show up and the function populateData() isn't called either. Any advice on how I could achieve what I am trying to do?
Thanks in advance!

How to access runtime controls from another form? (C#)

I have a form (Form1) and a button on it. When I press that button, I create runtime panels stored in an array of panels, declared like that:
Panel[] Panouri_variabile = new Panel[20];
If I press the button, a panel is created. If I press the button again, another panel is created underneath the previous panel and so on.
Each panel has a textbox inside it. Obviously, the textboxes are stored in an array of textboxes, declared like that:
TextBox[] Nume_variabila = new TextBox[20];
The user writes something in each textbox of each panel.
Now, I want to access the data written by the user in those textboxes, from another form, like that:
Form1 form = new Form1();
form.Panouri_variabile[i].Nume_variabila[i].Text
That could be easily done if the panels and the texboxes are created at design-time, by simply setting the Modifier property of all controls to public.
The problem is that they are created at run-time, so I can't change the Modifier property.
After a lot of searches I found the following posible solution:
Panel new_Panel = Panouri_variabile[i];
And then declare the following property at the same level as the event - handlers are (class-level I think)
public Panel new_Panel { get; private set; }
I noticed that I can see the new_Panel from another form, so I can access it like that:
Form1 form = new Form();
form.new_Panel
but the problem that it is not indexable! I have an array of panels (and an array of texboxes) so I should access them using an index, as I specified above!
Is there a way of accessing those texboxes from another form? Or should I create them design-time?

C#, WinForm: cannot set designer-created-control with code-created control

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.

Winform & user control - C#

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?

Categories

Resources