I have fixed my form load problem. I changed it to where the main menu wasn't being called on load event and that fixed the issue. Now my retrieve event gets the version but never passes it to my form.
Here is my code for transferring process:
Where the information is being pulled from:
public string VersionPass { get; set; }
VersionPass = rtxtBoxNewVersion.Text;
This is the main menu where the value will be stored till they click the assign button. This is where it gets the value from the form.
public string VersionNum { get; set; }
VersionEditor newV = new VersionEditor();
newV.ShowDialog();
VersionNum = newV.VersionPass;
newV.Dispose();
Form being transferred to I am using form load because the value will not change: It never get the value into the PassedVersion = passedVersion.VersionNum; field.
MainMenu passedVersion = new MainMenu()
string PassedVersion;
private void Notification_Load(object sender, EventArgs e)
{
PassedVersion = passedVersion.VersionNum;
rTxtBoxVersion.Text = PassedVersion;
}
Having to guess a bit here, but ...
1) Take out new MainMenu() from the Notification_Load call. This is probably stopping the dialog being created properly.
2) If you want to share information you either need to pass it to the new object, for example when you create it:
MyObject = new MyClass(SomeObjectToTellItAbout);
// or maybe like this:
MyObject.InterestingInfo = SomeOtherObject;
If it's truely global information (app version, for example) you could make the info to share static (and then access it like this: MainMenu.MyAppVersion).
Edit based on comments:
You want to get an understanding of classes vs objects. A class is just a design; it's a concept. For example "human". An object is an instantiation of that class/concept/design, for example me. And you (another object). I can't find your name by saying h = new human(); h.name() and nor can you find your version by making a new MainMenu and asking it what version it is! Hope that helps.
Related
I've been working on making a project of mine more modular. Something I've wanted to do is have multiple buttons use the same function when they perform a similar action, but with different values. I've been stuck on trying to apply this to the following situation:
"When this button is clicked, have the user select an image, and then have a PictureBox display the selected image". Each button has its own PictureBox. All Controls have been created before runtime.
Hope that makes sense!
My last attempt can be seen in the code below- I have tried assigning the Controls(Button and PictureBox) to variables to be stored together in a class. There's 6 of these classes all included within a single List.
I've also tried to store only the Control Names and then using this.Controls.Find to retrieve the Controls.
I've tried quite a few smaller changes such as passing by reference, making the List static, and things such as that would (somehow)magically do the trick- I've gotten desperate.
public class score_control
{
public Button score_button;
public PictureBox score_picture;
public int picture_index;
}
public List<string> score_boxes_names = new List<string>();
public List<score_control> score_boxes = new List<score_control>();
public void add_score_control(Button button, PictureBox pictureBox)
{
score_control new_score = new score_control();
new_score.score_button = button;
new_score.score_picture = pictureBox;
new_score.picture_index = score_boxes.Count();
score_boxes.Add(new_score);
score_boxes_names.Add(button.Name);
}
public score_control find_score_control(string name)
{
int index = score_boxes_names.IndexOf(name);
return score_boxes[index];
}
public frm_settings()
{
InitializeComponent();
add_score_control(btn_score1_image1, pic_score1_image1);
add_score_control(btn_score1_image2, pic_score1_image2);
add_score_control(btn_score1_image3, pic_score1_image3);
add_score_control(btn_score2_image1, pic_score2_image1);
add_score_control(btn_score2_image2, pic_score2_image2);
add_score_control(btn_score2_image3, pic_score2_image3);
}
private void score_button_Click(object sender, EventArgs e)
{
Button image_button = (Button)sender;
if (ofd_png.ShowDialog() == DialogResult.OK)
{
score_control clicked_control = find_score_control(image_button.Name);
score_image[clicked_control.picture_index] = ofd_png.FileName;
clicked_control.score_picture.Image = Image.FromFile(ofd_png.FileName);
}
}
The problem seems centered around this line:
clicked_control.score_picture.Image = Image.FromFile(ofd_png.FileName);
The program throws a NullReferenceException , but clickedcontrol is being recognized in the Local Watch, as well as score_image being noted to be a PictureBox(as it should be).
When I instead held the Control Names in the class, I had broke this line down into multiple lines, but the following line produced a NullReferenceException:
Control[] find_control = this.Controls.Find(clicked_control.score_picture, true);
In this case, clicked_control.score_picture would be a string containing the PictureBox Name. Again, the Local Watch showed that it clicked_control was not null, and neither was score_picture.
Any help figuring out how to properly store a Control within a variable to later be used to modify that Control's properties would be greatly appreciated.
dontpanic was able to help me out with this one. The issue was actually outside of this code - it had to do with the line score_image[clicked_control.picture_index] = ofd_png.FileName;. The way score_image was initialized as an array was incorrect. Fixing that made everything work fine.
I have a query regarding maintaining a List in between two windows forms. It's for a project where I need to create an address book.
I have chosen to maintain the contact details in the form of a List. My first windows form (form1) contains a master copy of a list AddressBook, which contains the address book.
I hardcoded 4 entries into the address book list in order to experiment and get the simple functions such as 'add' and 'edit' working.
I have a second windows form called Add, in which I can add new entries to the list. This works fine. I can add a new contact in the ADD form and this shows up in the initial form1, master form.
My problem arises in the EDIT form. I pass the AddressBook (master) list to the EDIT form. The EDIT form takes the master list and I am able to manipulate the records in that list. However when it comes to sending back the new list to the master page (form1), it does not pick it up. I am using the same code as I do in the ADD form which successfully sends back the new list. However this code does not work when sending back an edited list.
Here is my AddressBook property within form1
public List<Contact> addressBook;
public List<Contact> AddressBook
{
get { return addressBook;}
set {addressBook = value;}
}
Within EDIT:
public Edit()
{
InitializeComponent();
temp = Master.AddressBook; // temp is the temporary List I update within EDIT
}
** I then have my algorithm which successfully lets me EDIT the list temp. the list temp now has the edited list**
then when I hit the save button, I use the following code;
Master.AddressBook = temp;
All I need is for the list temp to be sent back to form1.
the code Master.AddressBook = temp; WORKS for when I add values to the list through the ADD form.
ADD FORM:
public Add()
{
InitializeComponent();
temp = Master.AddressBook;
}
**** code to add a new record into the list temp. the new record is called newRecord**********
private void btnAddClose_Click(object sender, EventArgs e)
{
stor.AddressBook = temp; // when I hit close on the form, it updates the master list AddressBook
this.Close();
}
This is all probably very poorly worded but in essence the only bit where my code fails is when I want to change my master Addressbook within form1 by replacing it with the list temp, which is the edited list from my EDIT form.
I think it's something to do with my AddressBook property. But this doesn't explain why I can replace AddressBook with a list containing new records but I can't replace it with a list containing edited records.
One way to accomplish this would be to make the list in Master static.
Master:
public static List<Contact> AddressBook { get; set; }
Note: You do not need the backing variable, and if you do want to use it, best practices would suggest that it be private. If you do decide to use it, it will also need to be static.
In the Add form, you would then gather the data to create a new Contact object and temp should, in fact, be just a Contact object.
Add Form:
private Contact newRecord = null;
public Add()
{
InitializeComponent();
newRecord = new Contact();
}
/**** code to add the user-input to the new Contact object ****/
private void btnAddClose_Click(object sender, EventArgs e)
{
Master.AddressBook.Add(newRecord);
this.Close();
}
Hope this helps.
This is where the Singleton pattern comes in handy: Implementing Singleton in C#
You will notice Application Settings uses this same patttern to allow you to globally access it without having to pass it around.
When I use a Singleton I typically make the class name like (TypeName)Manager (ex: AddressBookManager).
So the class might be something like this:
public static class AddressBookManager
{
#region Singleton
static readonly AddressBookManager instance = new AddressBookManager();
private AddressBookManager(); // prevent creating instances of this
public static AddressBookManager Current { get { return instance; } }
#endregion
AddressBook master = new AddressBook(); // the master address book
public AddressBook Master
{
get { return master; } // get the master address book
set { master = value; } // set the master address book
}
}
Then in each form you would access it like so:
var addressBook = AddressBookManager.Current.Master;
addressBook.Add(newRecord);
The problem you are experiencing with the Edit functionality probably has something to do with the way you are using temporary lists. By using a static, global list and merely adding/editing items inside of it, you don't run that problem. Since your Contact items are a class (not struct), their changes will be reflected in the list automatically since they are reference types.
The great part about Singleton classes is the ability to access them from anywhere in the project. The only caveat is that you need to be extra cautious when working with multi-threaded applications and Singleton classes.
EDIT::
This might be simple for some but right now it has me confused. I am working on a project and when the submit button is pressed,create either a person or an employee based on the above checkbox. Put all of the form data into the class object using either the constructor or properties. Display all of the class information using the ToString method and a messagebox.
My question is::
When it is asking when the submit button is pressed, create a person or an employee based on the above checkbox.Would I use what is above the checkbox or below.
Also to put all of the form data into the class object using either the constructors or properties. I'm Not to sure how to do this.
Display all of the class information using a ToString and a messagebox. I understand how to do a messagebox but not with a ToString.
Now I already have two classes and those names are Members and Employees. Under the Members I have Name, Age, and COB. Under the employees I have Salary and JobTitle. The only time that the salary and jobtitle comes up if the user check the checkbox that says is person employee.
I am sorry if I confuse people I myself is kinda confused with what is being asked. The software I am using is Microsoft Visual C# 2010 Expressed.
The code I have so far don't know if it is right or not:
private void button1_Click(object sender, EventArgs e)
{
Members obj = new Members(); <---This is what is I am assuming being asked when
obj.Name = ""; its says create either a person or an employee
obj.Age = ""; based on the above checkbox.
obj.COB = "";
Employess obj1 = new Employess(); <-- here I am trying to put all of the form
obj1.Salary = ""; data into the class object using either
obj1.JobTitle = ""; the constructor or properties.
Console.WriteLine(obj.ToString());<--- this is the messagebox I am being asked to do its not all the way done.
}
From what I get from your code is you have taken two classes for employees and members and you want to store their information in objects of respective classes based upon your checkbox selection. I suppose you are working in windows forms because you have specified the button_click event.
If that's the case:
private void button1_Click(object sender, EventArgs e)
{
if(checkbox1_Member.Checked==true)
{
Members obj = new Members();
obj.Name = "";
obj.Age = "";
obj.COB = "";
MessageBox.Show(obj.Name+ " :: " +"obj.Age.ToString());
}
else if(checkbox2_Employee.Checked==true)
{
Employees obj1 = new Employees();
obj1.Salary = "";
obj1.JobTitle = "";
MessageBox.Show (obj1.Salary.ToString()+ " ::"+obj.JobTitle.ToString());
}
}
Your question is quite vague but let's make a ton of assumptions:
You have a checkbox you've renamed to 'checkEmployess'. (I'm not sure if you meant 'employee' but let's just go with it.)
You have text boxes on your form for all of the stuff the user has entered with sensible names.
All the input is in text at the moment.
So, you need to check whether the checkbox is ticked/checked with an if statement and create the correct sort of object:
private void button1_Click(object sender, EventArgs e)
{
object dude; // if you use inheritance then this could be of the base class's type
if (this.checkEmployess.Checked)
{
// it's an employess
Employess employee = new Employess();
employess.Salary = textSalary.Text; // this copies the value of the control into your object
employess.JobTitle = textJobTitle.Text; // however for this example we've assumed every control is a text control and your object has only string properties
dude = employess;
}
else
{
// it's a member
Members member = new Members();
member.Name = textName.Text;
member.Age = textAge.Text; // this in particular should be made numeric
member.COB = textCOB.Text;
dude = member;
}
MessageBox.Show(dude);
}
That's the basic object creation done. You could add a ToString method to these two classes to format their properties for display. (This approach is a bit crude but will work so stick with this for now.)
Improvements you can then make are:
Use input controls that are more suitable for the type of input. E.g. numeric controls for numbers, &c.
Use object initializers for constructing these objects.
Use methods to correctly format these two types of objects for display).
I've created a custom user control with a grid. I'd like to bind this grid once, and use it over and over again in my app. If I put the binding within the control, the data is retrieved as many times as I use the control. How do I bind it only once??
public ClientLookUp()
{
InitializeComponent();
vw_clientsTableAdapter.Fill(dsclientlkup.vw_clients); //This occurs as many times as I have the user control, instead of just once.
}
Well anything you put in the constructor will be executed every time you construct the object!
What about providing an Initialize method that you can call whenever you need to reload the data??
If you want to load the data only once, then load it either into a static variable or a separate class that is referenced by the control.
If you really want to use the same single grid in your control over and over, you could create a single, static grid, and have your ClientLookUp constructor add it to the right place—Panel, or whatever—whenever a new one is created.
Before you go do this road however, ask yourself if this is really what you want to do. Having the same identical grid existing in many places may cause you problems down the road. If you want to support in-grid editing, you'll find that changing one value changes the identical value in all your other grids..
EDIT
I tried getting the below code to work, but I'm not sure this approach will be possible. It seems as though the minute you try to attach the same UI element into more than one place, it gets moved out of the last place you put it; it doesn't look like you can have the same grid being in more than one place at once. This makes sense when you think about it.
Here's the code I tried. Maybe it will be of some use to you.
public UserControl1()
{
InitializeComponent();
this.Controls.Add(myStaticGridView);
myStaticGridView.Dock = DockStyle.Fill;
}
static DataGridView _staticGrid;
public DataGridView myStaticGridView
{
get
{
if (_staticGrid != null)
return _staticGrid;
_staticGrid = new DataGridView();
_staticGrid.Columns.Add("A", "A");
_staticGrid.Columns.Add("B", "B");
_staticGrid.Columns.Add("C", "C");
_staticGrid.Columns[0].DataPropertyName = "A";
_staticGrid.Columns[1].DataPropertyName = "B";
_staticGrid.Columns[2].DataPropertyName = "C";
_staticGrid.DataSource = new[] {
new { A = "someA", B = "someB", C = "someC"},
new { A = "someA", B = "someB", C = "someC"},
new { A = "someA", B = "someB", C = "someC"},
new { A = "someA", B = "someB", C = "someC"},
};
return _staticGrid;
}
}
And then loading the control like this:
private void button1_Click(object sender, EventArgs e)
{
flowLayoutPanel1.Controls.Add(new UserControl1());
}
I have a winforms application.
I have a textbox on one form (call F1) and when a button is clicked on this form (call F2), it launches another form.
On F2, I want to set a string via a textbox (and save it to a variable in the class), and then when I close this form, the string will appear in a label in F1.
So I am basically sharing variables between both forms. However, I can't get this to work correctly. How would this code look?
I would add a new property to form2. Say it's for a phone number. Then I'd add a friend property m_phone() as string to form 2. After showing an instance of form2 but before closing it, you can refer to the property m_phone in form1's code.
It's an additional level of indirection from Matthew Abbott's solution. It doesn't expose form2 UI controls to form1.
EDIT
e.g.:
public string StoredText
{
get;
private set;
}
inside the set you can refer to your UI control, like return textBox1.text. Use the get to set the textbox value from an earlier load.
And:
public string GetSomeValue()
{
var form = new F2();
form.ShowDialog();
return form.StoredText;
}
Just ensure that StoredText is populated (or not, if appropriate) before the form is closed.
Are you showing the second form as a dialog, this is probably the best way to do it. If you can avoid doing shared variables, you could do the following:
public string GetSomeValue()
{
var form = new F2();
form.ShowDialog();
return form.TextBox1.Text;
}
And called in code:
Label1.Text = GetSomeValue();
This might not be the most efficient way of approaching, but you could create a class called DB (database). Inside this class, create variables like
public static bool test or public static bool[] test = new bool[5];
In your other forms, you can just create an instance. DB db = new DB(); then grab the information using db.test = true/false. This is what I've been doing and it works great.
Sorry, I'm only like a year late.