I have a usercontrol where I want a property that can list all the other instances of the same usercontrols in the Windows Form.
Eg. I have a simple usercontrol (sidebarbutton). I drag-drop 2 instances of it in a UserForm. Now I want a property (in the usercontrol itself) that can list both of them.
I have written this property. However, when used in Property Browser Window of Visual Studio, it allows me to add new instances of sidebarButton control.
private List<SidebarButton> _sidebarButtons;
[Browsable(true), EditorBrowsable(EditorBrowsableState.Always), Category("Roshan")]
public List<SidebarButton> SidebarButtons
{
get { return this._sidebarButtons; }
set { this._sidebarButtons = value; }
}
How to add the 2 instances that I drag-droped in the form in this property.
I know the property needs to be modified but don't have a proper direction to take. Please HELP me.
One way of doing this could be that upon addition of the user control to the form, the user control notifies all other user controls of that type that it now exists. Your user control can implement an interface like so:
public interface INotifiable
{
public void AddToList(INotifiable newButton);
}
When the user control is added to the form you iterate through all the controls and check whether they implement this interface. If they do you call the AddToList method and pass the newly added control to it.
Related
This is more so a general question than an issue I have. I have a form with 30+ controls that I will use to populate a model, which eventually ends up in a database.
I was wondering, however, if I could just pass the whole form object to another class, and pull the contents out in the other class without setting up a whole bunch of getters and setters.
Let's say I have a form Form1, and I make this call:
OtherClass.Validate(this)
Then, in the OtherClass (which is in a different project in the same solution) I have:
public static void Validate(Form1 myForm)
I have played around with this a little. In the Validate() method, if I put a watch on myForm, I can see all the form controls and properties, but I don't know if there is a way to just pull them out. If I type myForm., intellisense shows me all the standard form methods and properties, but not the controls and properties specific to the form. Has anybody tried this successfully?
You may grab controls from a form object using
myForm.Controls
This gives you a collection of controls within the form. You may iterate through them with a foreach loop.
Example with this form containing two buttons. You may use the following code to get the controls text.
public static void Validate(Form1 myForm)
{
foreach (Control control in myForm.Controls)
{
string text = control.Text;
Console.WriteLine(text);
}
}
Triggering the above function prints the following to the console. (Using this form)
button2
button1
This method works for TextBox and other controls too. However, it may be trickier if you have controls within controls. You may solve that by making a recursive function.
Each control on a form has a property called "Modifiers":
It is "Private" by default (for a reason: UI is the most likely subject for changes, any logic outside the form should not depend on controls. One control can be replaced with another, a group of controls can be replaced with a custom control. When controls are public, such change is not incapsulated and triggers changes in many parts of the system)
Controls which are added on a form, are serialized into C# code in form.designer.cs file. Code for textBox1, when it has modifier Private:
private System.Windows.Forms.TextBox textBox1;
Change it to Public like shown on a screenshot, and it will become
public System.Windows.Forms.TextBox textBox1;
Public controls will be accessible like any other public fields:
public static void Validate(Form1 myForm)
{
if (String.IsNullOrEmpty(myForm.textBox1.text))
{
// do smth about empty field
}
}
I need to know, how I can access lables or buttons other than in my "Form1"-Class.
My Problem:
I created for example labels, buttons via the design viewer. Now I can access
them in my Form1 Class. (testlabel.Enabled == true) just for example.
What I CAN'T do: Access those labels, buttons in another class! Let's say
I have a class "second-class" and I want to have a method there, that changes
the property of a label to
`testlabel.Enabled == false`
That's not possible, because in that "second-class" it's not visible.
So, is there an obvious easy solution to make those controls accessible in other classes?
Create a method in that (Second class) which takes that component (Label or Button or whatever you want to modify) as parameter into that method.
public void disableLabel(Label inputLabel)
{
inputLabel.Enabled == false
}
Create a method like the above.
Now in the form1 class you just to need to call that method and pass your Label into that method to Disable it.
SecondClass objSecondClass = new SecondClass();
objSecondClass.disableLabel(testlabel);
Every control in a form class is created by default with its property Modifiers set to Private
If you change it to Public you could access the control instance from another class.
However this is really a bad practice to follow. Messing with the visibility of the control is dangerous and could cause very complicated bugs to resolve.
If you really need to change something in your form class then provide a public method and call this method to change the internal functionality of the target form
I just started breaking up my GUI application into UserControls. I have a TabControl with a bunch of TagePages. Obviously my MainForm.cs file was filled up with tons of events and controls etc and it got very messy quick.
So a previous question gained me the insight of how to create a UserControl. I intend on creating a UserControl for each TabPage and I was wondering how I can interact with Components on the main form or other UserControls.
Here is an example of a TabPage that I have made using a UserControl, which needs to Enable or Disable a button depending which TabPage is currently selected. Is this proper usage or is there a better way?
public partial class TabDetails : UserControl
{
private RequestForm fRequestForm;
public TabDetails()
{
InitializeComponent();
}
public void CustomInitialization(RequestForm pRequestForm)
{
fRequestForm = pRequestForm;
pRequestForm.TabControl_Main.SelectedIndexChanged += SelectedTabIndexChanged;
}
private void SelectedTabIndexChanged(object pSender, EventArgs pEvents)
{
fRequestForm.Button_SubmitRequest.Enabled = fRequestForm.TabControl_Main.SelectedTab != fRequestForm.Tab_Details;
}
}
In the MainForm.cs constructor I call:
this.tab_Details1.CustomInitialization(this);
This doesn't look like a good use of a user control. The user control should not decide how things in the form should behave when something is changed in the user control. A user control should be unaware of its container and should operate in any container.
The user control should notify the form that something has changed without telling what's the internal implementation and the form should decide what to do.
Example:
A user control named "NameUserControl" consists of TitleComboBox, FirstNameTextBox and LastNameTextBox. The user control wants to notify when one of the values has changed.
Wrong Way:
Create events:
TitleComboBox - SelectedIndexChanged.
FirstNameTextBox, LastNameTextBox - TextChanged.
The problems here:
You expose the internal controls behavior. What will happen if you want to change the TitleComboBox to TextBox? You'll have to change the event name and implementation.
You expose the fact that you use exactly 3 different controls. What will happen if you want to use the same text box for first and last name? You'll have to delete one event and change the name of the other.
Good Way:
Create only a single event: NameChanged and expose 1 property of FullName or three different properties for the values.
Either way the form subscribe to the event and decide what to do next.
Another thing to think about: the more you add more functionality to your user control, you either make it less reusable or you make its code more complex. For example, if you add validation inside the user control, you'll find one day that you need it without validation, so you'll add a property "bool ValidateData" or it will be so complicated that you'll need to build another control. One way to solve that is to build very small user controls, but combine them in one or more bigger user controls that fit all your current needs.
I have created a customize windows form and I just don't know how should I set properties to it.
for example I've created a form with a progress bar, button, and a label and want to set the text of the label, the value of the progress bar, and to get access to the buttonClick Event method form the windows form application that uses the control.
In other words just get access to all the default properties of each control inside.
Is it possible? and how should I do it?
thanks very much!
If I want to to get access to the buttonClick Event method how should I do it?
You need to cast from Control to the type of your custom control before you can access the properties you have defined.
var myCtrl = (MyControl)controlRef;
myCtrl.MyProperty = xxxx;
This code assumes that MyProperty has been declared as public.
If I understand your question correctly, you want to expose controls on a form to outside code.
One way to achieve this would be to declare accessible properties on the form, for example:
public ProgressBar MyProgressBar
{
get { return progressBar1; }
}
If you wish to only expose certain properties of the controls, you could also have properties that access these directly, like so:
public int MyProgressBarValue
{
get { return progressBar1.Value; }
set { progressBar1.Value = value; }
}
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.