I am trying to refill GridView on a Usercontrol (DashboardCTR) by calling a method (Reload_Dash) in the Usercontrol from a different form (FrmOpenShop) without creating a new instance of the UserControl.
I achieved this same task when using form like this:
foreach(Form appForm in Application.OpenForms)
{
if(appForm.Name=="formName")
{
(Application.OpenForms["formName"] as formName).MethodName;
}
}
But for Usercontrol, am not user of how to get this done, i was hoping I could get it by following the approach stated above like this:
foreach(UserControl control in Application.OpenForms)
{
if(control.Name=="DashboardCTR")
{
(Application.OpenForms["DashboardCTR"] as DashboardCTR).Reload_Dash;
}
}
But this didn't work, some idea would be helpful.
Thanks.
A component's/control's Modifiers property annoyingly defaults to private when created, or if not that case, try adding in these protection modifiers: public and static, public goes before static.
The public modifier makes the method available to the user if the constructor is used.
The static modifier forces the method available only if the type is mentioned without using a constructor. This allows you to force a reload/redraw on the UserControl grid view or whatever. Allowing you to refresh it anytime you want.
Related
I am working on project winForm application. Am trying to add a UserControl to a Panel on the main Form.
Here is what I did, I created a public static method on the Main Form so I can call it from anywhere without instantiating the main form.
public static void showUC(UserControl uc)
{
pnlContainer.Controls.Clear();
GC.Collect();
uc.Dock = DockStyle.Fill;
pnlContainer.Controls.Add(uc);
}
I am getting a compilation error "An object reference is required for a non-static field, method or property".
If I create the method as non-static the compilation error will be gone but I won't be able to call it without creating object of the main form.
What I want to achieve is to be able to open any UserControl inside the Panel 'pnlContainer' on my Main Form 'frmMain'.
When the main form loads I want to calling the method without instantiating the main form again. For example
public static void showUC(UserControl uc)
{
pnlContainer.Controls.Clear();
GC.Collect();
uc.Dock = DockStyle.Fill;
pnlContainer.Controls.Add(uc);
}
I want to be calling this method like this
frmMain.showUC(new ucClientList);
From another class.
Let me explain exactly what I want to achieve.
I have a Form Control named 'frmMain' which contain a panel control named 'pnlContainer' and I want to be loading UserControl into it, I have UserControl1 and UserControl2.
Now I run the program and the frmMain loads, I wants to add UserControl1 to the panel pnlContainer and I have a button inside the UserControl1 which is supposed to load UserControl2 into the same panel on the Main Form when I click on it. How do I implement this?
If you really want to do so you can write your code like this:
public static void showUC(Control uc, Control pnlContainer)
{
pnlContainer.Controls.Clear();
uc.Dock = DockStyle.Fill;
pnlContainer.Controls.Add(uc);
}
and call it like this:
showUC(new someControlType(), someControlContainer);
No need to call the GC; do leave it to the system to clean up matters!
And a static function needs to know all objects it is supposed to work with, so you need to pass in the container as well.
Finally new needs paranthesis with (optionally) parameters..
I made the signature of the new control Control so you can pass in any control; and for even more flexibility the container is also Control. Note that this still allows you to pass in the Form! Of course you may want to go back to more restricted types..
Update
If you want to switch between two UserControls that both sit in the same container you can use this function:
public static void showUC(Control uc)
{
foreach (Control ctl in uc.Parent.Controls) ctl.Visible = ctl != uc;
}
It can access the other one via the Parent of the calling one. In the UC write:
private void button1_Click(object sender, EventArgs e)
{
Form1.showUC(this);
}
You could modify to actually create the UserControls instead of Hiding/Showing them; but you would lose their state each time..
If that is what you want, you may consider changing the name to something like switchUcFrom or showOtherUC; after all it doesn't 'show this' but rather 'hide this and show the other UC'
How can I use my UI form controls from another class? I want to work with these controls in another class, then call it into my main form. The problem is that the new class I created can't seem to access the label or the textboxes of these controls and I keep getting an error.
How would i solve this issue?
Error Messages:
FirstName_text is inaccessible due to its protection level
First_Name_label is inaccessible due to its protection level
Color does not exist in the current context
public void Checker()
{
//First Name Validation
if (Regex_Static_Class.FirstNameRgex.IsMatch(FirstName_text.Text) == false)
{
First_Name_label.Text = "invalid first name";
Error_Lable.ForColor = Color.Pink;
}
}
I guess First_Name_label is a UI label and it must be accessible form your other class too.
Maybe make a setter method to fill in text into your label.
I would say that you have to set Modifiers property for your controls to public or internal in Forms Designer to access it from another class. Control's instance is protected by default.
That's the answer to your question. Another thing is that it's not the best idea to do that. You shouldn't access form's controls outside of form directly. Form class should encapsulate its controls and expose an interface to change them, for example.
Also Color doesn't exists most probably because you don't have proper using in your another class.
It has nothing to do with conditions (references to conditions removed from the original question).
I have a custom control that I'm also using as a DataGridView control. This custom control has a method called SetHttpClientand I pass a HttpClient object as parameter.
How can I call this method from the parent form? (The parent form only knows about the instance of the class deriving from DataGridViewTextBoxCell)
You should build a nice structure for this. For example if you have two Forms, and in Form 1 you have the Grid, which you want to refresh From Form 2. If you want to open Form 2, you should pass the instance of the Grid from on creating the instance.
Or a second way, Form 2 provide an event which will be subscribed in Form 1. And the event is called if the Grid should be refreshed. You can than pass the HttpClient over the Args-Object to Form 1.
Please tell me, if i misunderstand you.
In my opinion you should use a ViewModels to communicate with View instead of one View execute action on second View.
So, for example your View like
CustomersView contains CustomersViewModel in DataContext, if you execute a operation GetData you make it in CustomersViewModel and the result put to DataGridView.
This solution moves responsibility of providing data from class DataGridView to CustomersViewModel. The ViewModel can use some Service or other mechanism to provide you data using HttpClient.
I know that's not straight answer for your question, but is good solution for your problem.
In this example https://msdn.microsoft.com/en-us/library/ff798384.aspx you have method GetParts, you can imagine that the body of this method contains HttpClient and get the data from a website.
May be you're talking about access modifiers like private, public, internal.
If so, then in child form make access modifier like public or internal.
And in parent form just make needed call.
public partial class ChildForm : Form
{
public ChildForm()
{
InitializeComponent();
}
internal String HellowWorld_mt(string SuffixValue)
{
return "hello world and "+ SuffixValue;
}
}
public partial class ParentForm : Form
{
public ParentForm()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
ChildForm cf = new ChildForm();
cf.Show();
string resp = cf.HellowWorld_mt(" extra!");
this.Text = resp;
}
}
More about that: Access Modifiers (C# Reference)
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?