I have a Class named Testing and a Form called TitleScreen. In TitleScreen I have a textBox1 who's text I would like to be passed to a Class and then pass it back to my Form into a textBox2.
I know how to do only the basics in C# so if you try and make it simple as possible.
In your Class:
public class Class1
{
public static string SeparateName(string fullName)
{
string[] wordsInText = fullName.Split(' ');
return wordsInText[0];
}
}
In your Form:
private void button1_Click(object sender, System.EventArgs e)
{
textBox2.Text = Class1.SeparateName(textBox1.Text);
}
"I highly recommend that you read a book or tutorial that targets new users, otherwise there will be holes in your understanding of the language and the frameworks."
It sounds like you want to perform an operation on the textbox's value and then print the result in another textbox.
You can write a method (function) that accepts an argument of type String and perform the operation in that method. The method can then set the Text property of the textbox to the result.
If you're asking how to input code in a winforms project, you can double-click the background of the form to reach its code. (At least in Visual Studio)
If you don't know how to do the above suggestions, I highly recommend that you read a book or tutorial that targets new users, otherwise there will be holes in your understanding of the language and the frameworks.
I would suggest you want to look at the concept of data binding, whereby you bind the controls on your forms to the properties of the underlying objects (instances of your classes).
Binding removes the need to write code to cross-load the data from the class into the form and back again, instead you can then say "text box 1 is bound to this property of my class". Then, when you update the value of the textbox the data is automatically placed into the chosen property of your class instance. Typically you then have a save button that calls a save method on your class to persist the data to your data store (database or whatever).
It is perfectly reasonable to bind more than one control on your form to the same property on your underlying class, so in your example you can bind both textBox1 and textBox2 to the same property on your class. Then, once you've implemented databinding, when you change the value in textBox1, the value will automatically be reflected in textBox2, either on each keystroke or when the field is validated (typically when you move focus to another control).
This is the microsoft documentation on Winforms binding which covers everything you need: https://msdn.microsoft.com/en-us/library/ef2xyb33(v=vs.110).aspx
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
}
}
Here is the scenario:
I have an Edit Dialog form with a BindingSource and some data bound text boxes on it:
I pass an entity to the form constructor and it gets loaded into BindingSource.DataSource which causes the data bound controls to show the values of properties.
The problem is as the user edits the values in TextBox controls and Validating events get passed, the data source gets changed though it is not applying to DB but it still can confuses the user as he sees the edited values on the List Form, till next application restart.
so the question is: How to prevent binding source from reflecting changes instantly or how to roll them back?
I inherited the binding source and created a new binding source like this:
public class SuperBindingSource:BindingSource
{
#region Properties
public object DataSourceBeforeChange { get; private set; }
#endregion
#region Methods
public void ResetChanges()
{
this.DataSource = this.DataSourceBeforeChange;
}
#endregion
protected override void OnDataSourceChanged(EventArgs e)
{
base.OnDataSourceChanged(e);
DataSourceBeforeChange=this.DataSource.DeepClone();
}
}
Though I am not sure if it is a good approach.
As an option, when setting up data-bindings, you can set them to update data source never.
Then at the point that you want to apply changes, for example when pressing OK button, you can set data-bindings to update data source on property change and then call end edit method of the binding source.
For Cancel button, you don't need to do anything, because the data source is not updated.
Example
In form load event:
this.BindingContext[bindingSource].Bindings.Cast<Binding>().ToList()
.ForEach(b=>b.DataSourceUpdateMode= DataSourceUpdateMode.Never);
When pressing OK:
this.BindingContext[productBindingSource].Bindings.Cast<Binding>().ToList()
.ForEach(b => b.DataSourceUpdateMode = DataSourceUpdateMode.OnPropertyChanged);
productBindingSource.EndEdit();
You can download/clone the full source code:
r-aghaei/SuspendDataBindingExample
You can use the SuspendBinding method after the values are loaded.
After that the values should not update the source until you call ResumeBinding:
SuspendBinding and ResumeBinding are two methods that allow the temporary suspension and resumption of data binding in a simple-binding scenario. You would typically suspend data binding if the user must be allowed to make several edits to data fields before validation occurs. For example, if one field must be changed in accordance with a second, but where validating the first field would cause the second field to be in error.
According to the documentation you should be able to use this with your textboxes. If the user clicks Ok to save the values you resume the binding and if he cancels you don't.
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 have a main form with some buttons, textboxes, labels, etc.
On a second form I would like to copy the text from the main forms textbox onto the second form.
Have tried:
var form = new MainScreen();
TextBox tb= form.Controls["textboxMain"] as TextBox;
textboxSecond.Text = tb.Text;
But it just causes an exception. The main screen textbox is initialised and contains text.
When I hover over form I can see all the controls are there.
What am I doing wrong?
Looking at the original code, there are two potential reasons for the NullReferenceException you are getting. First, tb is not defined in the code you provide so I am not sure what that is.
Secondly, TextBox textbox = form.Controls["textboxMain"] as TextBox can return null if the control is not found or is not a TextBox. Controls, by default, are marked with the private accessor, which leads me to suspect that form.Controls[...] will return null for private members.
While marking the controls as internal will potentially fix this issue, it's really not the best way to tackle this situation and will only lead to poor coding habits in the future. private accessors on controls are perfectly fine.
A better way to share the data between the forms would be with public properties. For example, let's say you have a TextBox on your main screen called usernameTextBox and want to expose it publicly to other forms:
public string Username
{
get { return usernameTextBox.Text; }
set { usernameTextBox.Text = value; }
}
Then all you would have to do in your code is:
var form = new MainForm();
myTextBox.Text = form.Username; // Get the username TextBox value
form.Username = myTextBox.Text; // Set the username TextBox value
The great part about this solution is that you have better control of how data is stored via properties. Your get and set actions can contain logic, set multiple values, perform validation, and various other functionality.
If you are using WPF I would recommend looking up the MVVM pattern as it allows you to do similar with object states.
PhoenixReborn is correct. The problem is that you are creating a new MainScreen, which means that new controls are created, so unless the text in your controls are initialized in the form constructor, they are going to be empty. Usually, the way to handle this is to pass the first form instance to the second form, like this:
SecondForm second = new SecondForm(this);
and in the second form:
public SecondForm (MainForm form)
{
// do something with form, like save it to a property or access it's controls
}
That way, the second form will have access to the first form's controls. You might consider making the properties you need to use public (in the designer properties pane). That way you can just do form.textboxMain.Text.
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.