C# Create, check, loop through objects [closed] - c#

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

Related

How to transfer value from List between forms? [duplicate]

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

WinForms Multi-Instance Forms with unique variables

New to C#; have been a VB.NET/VBA developer for years. Am currently working on an application for our off-site workers. I have a main switchboard form with a drop-down of project numbers. The user then has the ability to open a variety of form-based tools, to include a Budgets form. On change of the drop-down, I store a Program-scoped class variable, cJob which has multiple properties (customer, location, etc). On open of the Budgets form:
Form frm = new FieldBudgets.frmBudgets().Show();
I have a private static instance of cJob called meJob (new cJob).
When going back to the switchboard, the user, without closing that instance of the Budgets for, can open additional instances of the same Budget form with different project numbers selected.
Here is my problem (sorry it took so long to get here):
A Refresh button can update the data on the Budgets form, but the new meJob information from the last instance get carried to the other instance. How can I keep these separate? I thought the new meJob would stick with the individual instances.
As an aside, I do have a less than glamorous "solution" that involves a hidden textbox and reloading the new meJob on Refresh. If that is the best solution I get, so be it...
MJ
Dictionary<string,FieldBudgets.frmBudgets> myBudgets = new Dictionary<string,FieldBudgets.frmBudgets>();
myBudgets.Add("Budget1",New FieldBudgets.frmBudgets());
myBudgets.Add("Budget2",New FieldBudgets.frmBudgets());
myBudgets.Add("Budget3",New FieldBudgets.frmBudgets());
myBudgets.Add("Budget4",New FieldBudgets.frmBudgets());
myBudgets["Budget2"].Show();
You might put any unique fields and/or properties in the constructor for frmBudgets.

WinForms passing data between Forms [duplicate]

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)

C# - Get property in member class using Reflection

SHORT VERSION
What's the best way to use reflection to turn something like string prop = "part1.first_name"; into a System.Reflection.PropertyInfo, so that I can use the GetValue and SetValue functions?
LONG VERSION
I'm using ASP .NET MVC to build a questionnaire for my organization. It's very long, so it's divided into several different pages. Since it's not uncommon for us to get requests like, "Can you move this question to that page, and this other question to another page," I need to build this to be pretty flexible for a junior programmer to change.
My model is a complex class (it's got five member classes that have mostly primitive-typed properties on them).
So, I access it by doing things like Model.part1.first_name or Model.part2.birth_date.
Since the same model is used on all of the pages, but not all of the questions are on every page, I have ActionAttributes that essentially clear out all of the properties that were submitted on the form except for the ones that were displayed on that page (so someone can't inject a hidden field into the form and have the value persist to the database).
I want to make sure that I only save valid field values and don't let the user proceed to the next page until the current one is entirely OK, but I also want to save the values that are valid, even if the user isn't allowed to proceed.
To do this, I have a function that takes two instances of my model class, a reference to the ModelStateDictionary, and a string[] of field names like "part1.first_name" and "part2.birth_date". That function needs to copy all of the values listed in the string array that do not have validation errors from the first (ie, form-submitted) object into the second (ie, loaded from the db) object.
As stated above, what's the best way to use reflection to turn something like "part1.first_name" into a System.Reflection.PropertyInfo, OR, is there a better way to accomplish this?
var infoParts = prop.Split('.');
var myType = Type.GetType(infoParts[0]);
var myPropertyInfo = myType.GetProperty(infoParts[1]);
Assuming "part1" is your type. Although this is very limited and very dependent on the string being in the correct format and the type being in the current scope.
I would probably handle this differently, using data. I would keep, in the database, which step each question belongs to. To render that step, I would select the questions that match that step and have a model that contains a list of question id/question pairs. Each input would be identified by the question id when posted back. To validate, simply compare the set of question ids with the expected ids for that step. This way, to change which question goes in which step is to only change the data in the database.
If you do end up going down that road, you'll need to split the string into parts and recursively or iteratively find the property on the object at each step.
PropertyInfo property = null;
Type type = questionModel.GetType();
object value = questionModel;
object previousObj = null;
foreach (var part in questionId.Split('.'))
{
property = type.GetProperty(part);
previousObj = value;
value = property.GetValue(value,null);
type = value.GetType();
}
// here, if all goes well, property should contain the correct PropertyInfo and
// value should contain that property's value...and previousObj should contain
// the object that the property references, without which it won't do you much good.

Access/Set controls on another form

I'm not good at C# at all, I just don't get the logics. But VB I seem to understand alot better since it seems much more logical. Atleast to me.
So I'm run into something which isn't a problem at all in VB, accessing controls on a different form then the one you're currently in.
In VB, if I want to set the state of a button say, in Form2. I just type the following:
Form2.Button1.Text = "Text"
In C# I cannot seem to do this. Why? There must be a pretty good reason for this right?
Edit: So if I have this code, what would it look like to be able to access controls on the other form?
if (!AsioOut.isSupported())
{
SoundProperties.radioButtonAsio.Enabled = false;
SoundProperties.buttonControlPanel.Enabled = false;
SoundProperties.comboBoxAsioDriver.Enabled = false;
}
else
{
// Just fill the comboBox AsioDriver with available driver names
String[] asioDriverNames = AsioOut.GetDriverNames();
foreach (string driverName in asioDriverNames)
{
SoundProperties.comboBoxAsioDriver.Items.Add(driverName);
}
SoundProperties.comboBoxAsioDriver.SelectedIndex = 0;
}
Just tried to add this "SoundProperties SoundProperties = new SoundProperties();
And I do get access to the controls. But do I need to add this bit of code in both parts of this IF-statement? Seems like I do, but still, adding that line to the last part of this code doesn't do anything ang gives me the error message:
"A local variable named 'SoundProperties' cannot be declared in this scope because it would give a different meaning to 'SoundProperties', which is already used in a 'child' scope to denote something else"
Removing the line gives me the following error:
"An object reference is required for the non-static field, method, or property 'NAudio.SoundProperties.comboBoxAsioDriver'"
Here's the code after adding these lines in two places:
if (!AsioOut.isSupported())
{
SoundProperties SoundProperties = new SoundProperties();
SoundProperties.radioButtonAsio.Enabled = false;
SoundProperties.buttonControlPanel.Enabled = false;
SoundProperties.comboBoxAsioDriver.Enabled = false;
}
else
{
// Just fill the comboBox AsioDriver with available driver names
String[] asioDriverNames = AsioOut.GetDriverNames();
foreach (string driverName in asioDriverNames)
{
SoundProperties SoundProperties = new SoundProperties();
SoundProperties.comboBoxAsioDriver.Items.Add(driverName);
}
SoundProperties SoundProperties = new SoundProperties();
SoundProperties.comboBoxAsioDriver.SelectedIndex = 0;
}
Please don't hate me for saying this - but I think this is an issue that I've seen a lot of VB coders run into.
VB allows you to not deal with classes if you don't want to. When in C# you are adding a form to your project - visual studio is just making a class file for you that inherits from "Form".
In C# you have to actually instantiate this into an object and then work with that object. VB allows you to just access the class as if it was already instantiated - but it is actually just making a new "Form2" for you.
In vb if you want to have more than 1 actual "Form2" you would say something like this...
Dim window1 as new Form2()
Dim window2 as new Form2()
window1.Show()
window2.Show()
Now you will have two copies of "Form2" on your screen when you run this.
The difference between VB and C# is you also need to actually make(instantiate) your first copy of Form2 - C# will not do it for you.
Now to answer your question:
Once you have an actual object that has been instantiated - you need to actually make "Button1" public instead of private.
To do this - on Form2 - select Button1 and look at the properties...
Find the "Modifiers" property and set this to public.
You will now be able to see "Button1" on both window1 and window2.
Hope that helped.
You can access another form in c# too.
But you need a reference to the Form instance you want to interact with.
So you have to hold the variable of the 2nd Form instance and access it via this.
E.g.:
From the code of the first form call:
Form2 my2ndForm = new Form2();
my2ndForm.Button1.Text = "Text";
Be sure to set the access modifier of the Button1 to public or internal.

Categories