This question already has answers here:
Communicate between two windows forms in C#
(12 answers)
Closed 3 years ago.
I have a table named questions with a field name qcategory. In WFA I have a ToolStripMenu where I have a category named Simulation and a sub-category named B. So, I want to create a mysql SELECT where to select only rows which values are equal with sub-category value. (Columns qcategory from table has value B). This is the string:
static string dataA = "SELECT DISTINCT * FROM questions order by rand() limit 1";
The only problem is that I have 2 forms. One with menu and one where I want to make that select.
You should try to split your UI-code and your database code. This is called Layering (MVVM, MVC, MVP,...) but you don't have to!
There are several ways:
1) Make a class that both forms can reference and execute your database logic there. (that would be the cleanest way for now)
2) Create an Event in your Form with the menu and react on it in the other Form
3) Your menu Form holds a reference to the other Form and executes a Method on it passing the selected subitem.
In code
1
public static class SqlClass
{
public static void ExecuteQuery(string menuItem)
{
//execute query
}
}
Form 1
//menu changed...
SqlClass.ExecuteQuery(menuItem)
2
Form1:
public event EventHandler<string> MenuItemChanged;
//menu changed...
if(this.MenuItemChanged != null)
this.MenuItemChanged(this, menuitem)
Form2:
public Form2(Form1 otherForm)
{
InitializeComponent();
_otherForm.MenuItemChange += //... handle your sql code
}
3
private readonly Form2 _otherForm;
public Form1(Form2 otherForm)
{
InitializeComponent();
_otherForm = otherForm;
}
//menu changed...
otherForm.ExecuteQuery(menuitem);
For the examples, Form 2 is the form where you want to execute your query because there is the Method/Event-Handler defined that will interact with your database.
To understand the solution, you need a more high level perspective - you get an information in code behind of a Form (a Class) and you want to consume that information somewhere else.
In general you need a reference to the Form that holds the information you are interested in and it tells you the information when changed (Event) OR
the information source tells every interested destination (calls a Method). Then the Information source hold the references to the consumers.
Both concepts are the same just the direction of the communication (and reference) changes.
The alternative (Option 1) is that you move your information destination somewhere else (e.g. in a static class) and consume it there. The Mechanism of passing the information is pretty much the same (via a parameterized Method call) but it encapsulates the UI-colde (Form) from the Database code (SQL query execution)
Related
This question already has answers here:
Passing data between forms
(6 answers)
Closed 3 years ago.
I have List<Basket> sas = new List<Basket>(); in Form1.
And i need to output all values from this List in another form.
Edited: Now i have problem with outputing.
List<Basket> sas = new List<Basket>();
public Form1()
{
InitializeComponent();
foreach(Basket e in sas)
{
basketBox.Text += e.Name + Environment.NewLine;
}
}
I added elements in Form2, but when I try to output them in Form1 nothing happened.
There are several ways:
You can have the list as a static (global) variable in the form1 class and then use it in the other form.
Another solution would be to have a context class to be given to the other form when you construct it.
if by from you mean windows forms, then you can simply make your list public static, so you can have access to it everywhere.
If you are working with ASP.NET web forms then you probably should relay on your database.
PS: you can use the Singelton pattern or DI as well. but for the sake of simplicity stick with statics
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
such a weird situation appears in front of me. Here is the thing.
If I would do this in PHP or some other programming language it would be easy but in C# I dont know how can I achieve this.
Brief description of my problem:
I have a UserForm in C# with combobox. In this combobox I have as many items as there are in the database -> so its dynamically filled on the start of the application
Each item should represent single UserForm. So here is the problem, if user choses item and clicks on button check should be fired if that userform has been created, if its not, then a new (object ?) userform must be created. Normally I would delete and recreate new form everytime user choses new option but I want to keep those Userforms and create them once and then only hide them or show them, so textinputs etc. remain filled while application will run (but I dont thing that creating 15-20 UserForms at the start of the app is okay in terms of performance).
So what I was thinking of doing and what I tried:
I wanted to use the name of chosen item from the combobox and use it as a Object (UserForm) name. (also perform check if it already exists before creating) -> apparently this is not possible in C# to use string variable as object name
I googled about Dictionaries, but can I store there whole UserForms ?
Also I was thinking of creating all 15-20 Userforms at the beginning and then looping through them and show them or hide them.
Any ideas ?
This is a caching problem. You want to cache the forms.
So first you need a container for the cache, e.g.
var cache = new List<UserForm>();
Then, when a form is needed, you need a special method to search the cache and add to it if needed. Because there is more than one type of form, you'll want to use generics here:
T GetOrCreateForm<T> where T: UserForm, new()
{
UserForm f = cache.OfType<T>().FirstOrDefault(); //Search cache
if (f == default(T)) //If not found,
{
f = new T(); //Create it anew
cache.Add(f); //and add it to the cache
}
return f; //return the form we just created/retrieved
}
You would then call this method, passing the type of the form desired:
var form1 = GetOrCreateForm<Form1>();
form1.Show();
The above assumes there is one type of form (one class) for each row in the list. If you actually have a common form class, but they are distinguished by something else (e.g. maybe each form has a unique Name property that is set at run time) then you'd need a dictionary to tell the forms apart:
var cache = new Dictionary<string, UserForm>();
UserForm GetOrCreateForm(string name)
{
UserForm f;
if (!cache.TryGetValue(name, out f))
{
f = new UserForm { Name = name };
cache.Add(name, f);
}
return f;
}
var myForm = GetOrCreateForm("SomeUniqueName");
myForm.Show();
Environment: Visual Studio 2008, C#, SQL Server, Windows development, Multiuser, New Developer
I have a method in form A that I use to display textbox information there.
Also I have a button that displays another form when clicked (form B).
Form B is created with frm.ShowDialog();
Form B has the same textboxes on it with the same names, they are identical (copied and pasted from form A)
I want to use the method in Form A to display the information in Form B, rather than copying and pasting the method from form A into form B
I made the method in form A public and called it from from B but nothing displays in form B's textboxes. Why? I don't get any errors.
Should I keep it simple and put a copy of form A's method in Form B instead of calling the method in form A from form B? That's the only way I can get it to work.
Form A is for displaying customer information, Form B is for editing customer information.
I'm passing and returning information between the forms and that's all working.
The forms are not identical, i.e., form B doesn't have textbox for the customer's notes, they are edited in a separate form.
Thank you for your input.
you should use an info class and retrieve data from it both in form A and form B
don't use duplicate code, just use another class for logic \ info.
You can read more about it here
Make a model class whose members represent the data to be shown in both forms. In visual studio 2008 I believe there is support to create a project data source based on an object. Create the data source from your model class. Then, in both forms, add a binding source. Set the data type for the source to be the project data source. Then, the designer will let you select bindings for each control from the binding source. Finally, in the form's constructor, accept a model class instance, and set the binding source's data source to be that instance.
Even if you have the same textboxes with same names when you call formA you are just changing the instance of formA which means only the textboxes in formA are changed.
You have to understand that every class has its own instance separate from the other.
That does not mean though that you cannot access formB textboxes in formA. I can see that you want to consolidate; if I'm not mistaken what you have in formA method is something like:
public void methodA(Customer customer)
{
textboxName = customer.Name;
textboxAddress = customer.Address;
}
If you dont want to duplicate this then the other approach that I can think of is:
1.) Create an interface for all the duplicate properties.
public interface ICustomerForm
{
string Name {get; set;}
string Address {get; set;}
}
2.) Have the 2 forms implement the interface.
public class FormA : Form, ICustomerForm
{
public string Name
{
get
{
return _textBoxName.Text;
}
set
{
_textBoxName.Text = value;
}
}
}
Do the same for formB
3.) Create a static helper class where you just pass the customer class. e.g:
public static class FormHelper
{
public static UpdateCustomerInfo(ICustomerForm form, Customer customer)
{
form.Name = customer.Name;
form.Address = customer.Address;
}
}
4.) In your two forms just call the helper class and pass itself as the first parameter and the customer class as the second parameter.
//Method in formA
public void formA()
{
FormHelper.UpdateCustomerInfo(this, customer);
}
//Method in formB
public void formB()
{
FormHelper.UpdateCustomerInfo(this, customer);
}
This way you just have one line of code in your forms and the setting of info is on the consolidated helper class.
I'm trying to pass values between a few winforms, I've got a total of 6 winforms, that the user will cycle through. I'm passing values between the forms using TextBox and Label Controls.
When I open the Primary winform, then click a button to load the second winform, everything works fine (I can pass values to the First Form). My problem is that once I direct the user to another form and this.Hide(); the current (2nd Winform) then try to use the Third form to pass values to the first, I get the following error:
Object reference not set to an instance of an object.
I'm confused because the control that the should be passing the value is passing the value to the first Form isn't NULL
I'm using the same code to connect all the forms together.
public MainForm MainForm;
Then I'm trying to pass the values like so:
MainForm.textBox1.Text = txt_FileName.Text;
Note: All the TextBox and Label controls that are passing values between the forms are public
Anyone run into this? Or any Ideas?
.
You need to make sure that all your forms are instantiated (through new MyForm1()...). Just declaring a variable of type MainForm won't create a form instance - you'll have to do it. My guess is that one of your forms is not created yet when you try to access a control.
This is yet another reason to not to use public controls (see my comment too), since the lifetime of your controls are tied to the lifetime of your form. It's better to hide controls from public access and send data to the form through data objects - the form will set all those values to its own controls. This also makes validation a lot easier, since a control's value can only be set to values allowed by the form. If you set control values from the outside, you'll have a tough time validating them in all scenarios.
I assume you're trying to use modal forms that work similar to a wizard where users go from one form to the next, following a clear path. If so, you can do something like this:
// Data class to set data in Form2
internal class Form2Data
{
public string Name;
...
}
...
internal class Form2 : Form
{
public static DialogResult ShowDlg ( Form2Data oData )
{
Form2 oFrm = new Form2 ();
oFrm.SetData ( oData );
DialogResult nResult = oFrm.ShowDialog ();
if ( nResult == DialogResult.Ok )
oFrm.GetData ( oData );
return ( nResult );
}
private void SetData ( Form2Data oData )
{
// Set control values here
}
private void GetData ( Form2Data oData )
{
// Read control values here
}
}
...
// You call this as such:
Form2Data oData = new Form2Data ();
oData.Name = "...";
DialogResult nResult = Form2.ShowDlg ( oData );
// after the call, oData should have updated values from Form2
if ( nResult == DialogResult.Ok )
{
// show your next form in a similar pattern - set up data
// call form's static method to pass it and then wait for
// the form to finish and return with updated data.
}
You'd have to use a similar pattern in your other forms, too. This does require more work since you need to set up a different data object for all the forms but this way you can easily do validation before and after the form is shown (in SetData and GetData). It also encapsulates your program better, since controls are not accessible from the outside.
.Net 2.0 and later has a feature for windows forms called the "default instance", where it gives you an instance with the same name as the type. The purpose of this feature is for compatibility with code migrated from old vb6 apps. If you're not migrating from an old vb app, it's usually better to avoid the default instances. They will get you in trouble, such as you have now. Instead, create a variable to hold form instances you construct yourself.
You should pass the value by using the instance value of the form.
for example:
SecondForm secForm2 = new SecondForm();
secForm2.textBox1.Text = txt_FileName.Text
so if you pass the value from SecondForm to ThirdForm:
ThirdForm thiForm = new ThirdForm();
thiForm.textBox1.Text = textBox1.Text
Learning C#:
I have structure of
form1 (splitcontainer)
userformLeft (button + sub-panel)
userformDisplay (loaded into panel in userformLeft)
userformRight
I want to execute a method in userformDisplay from form1 (timer in form1).
And the other way around, let's say I have public property form1.mainTimer, can
I call it from userFormDisplay like
myLong = this.parent.parent.mainTimer;
or similar.
yes.. you can do this:
myLong = ((form1)this.parent.parent).mainTimer;
Similar problems of communicating between one form and another... whether attaching to "events" of one, or calling / setting values to/from each other. Here are a couple links to questions I've answered to in the past that may help understand the relationships to do so.
Sample 1 with explicit steps to create two forms communicating back/forth to each other
Sample 2 somewhat similar, but attaching to events between forms