I've stomped with a problem I've spent some hours trying to solve, with my very limited knowledge.
I have a listview in my form1 called listMachine
And I have a method in form1.cs such as
private void máquinaToolStripMenuItem_Click(object sender, EventArgs e)
{
machinename open = new machinename();
open.Show();
}
machinename.cs is another form, and I use that method to open my other form, with an object called open.
the machinename button is a simple form which just serves as an input receiver, it asks a name, we have to type it into the textbox, press a button and it receives the input.
This is the code that runs when you press the button
public void buttonAceitarnome_Click(object sender, EventArgs e)
{
if (textBoxnomenova.TextLength == 0)
{
toolTipEmptyname.Show("O nome da máquina não pode estar vazio", textBoxnomenova);
}
else
{
Variables.var = textBoxnomenova.Text;
//MessageBox.Show(Variables.var); debug purpose, the messagebox does carry variables.var text
obj.listMachine.Items.Add(Variables.var); //If I change the variables.var to "test" it will NOT add the item.
this.Close();
}
}
Also, I forgot to mention my Variables.cs class, I created it because it was the only way I found to pass variables from a class to another (machinename.cs to form1.cs), but still, the items are not added into the listview.
This is my variables.cs code
public static class Variables
{
public static string var;
}
The comments I added to the code also give you some extra debug info..
I didn't want to ask for online help, but couldn't solve this on my own :(
If I were you, I would first remove the Variables class.
Then, you'r first form/class is called obj.cs, am I right? Or is it form1.cs?
I made it look like this:
public partial class obj : Form
{
public static string text; //This is a variable that can be reached from
public obj()
{
InitializeComponent();
}
private void máquinaToolStripMenuItem_Click(object sender, EventArgs e)
{
machinename open = new machinename();
open.ShowDialog(); //I put ShowDialog instead of Show
addItem(); //This method is called when the showed dialog is closed (machinename.cs)
}
private void addItem()
{
listMachine.Items.Add(text);
}
}
and the machinename.cs class like this:
public partial class machinename : Form
{
public machinename()
{
InitializeComponent();
}
private void buttonAceitarnome_Click(object sender, EventArgs e) //This one can be private
{
if (textBoxnomenova.TextLength == 0)
{
//Something here
}
else
{
obj.text = textBoxnomenova.Text; //Initializing the public static variable
this.Close(); //Closes the form, next step will be to run the method in obj.cs
}
}
}
If I understood your question correctly, you wanted to add an item to the ListView called "listMachine" via a button in the form "machinename.cs". This code will do that. I hope it helps you.
Change the click event from private to protected.
protected void máquinaToolStripMenuItem_Click(object sender, EventArgs e)
Related
I made a class so when the user selects item from listbox it uninstalls that item, except the problem is I can't access the list box. I tried public aswell, but in the code of form1.cs the only thing clostest to that list box is
keep in mind name of listbox is ProgramslistBox
Ok guys I re edited this post;
private void button1_Click(object sender, EventArgs e)
{
if(ProgramsListbox.SelectedIndex == -1)
{
MessageBox.Show("Please select an item to uninstall!");
}
else
{
ProgramsListbox_SelectedIndexChanged("",EventArgs.Empty);
}
}
this code is the FORM1.CS class, and I have another class called UninstallItem.cs is where I want my code to be, this below is my other class
namespace PC_TECH_Registery_Cleaner
{
class UninstallItem
{
public void uninstallSelectedItem()
{
Form1 c = new Form1();
}
}
}
And this below is still in my FORM1.CS class, I was experimenting with it :
public void ProgramsListbox_SelectedIndexChanged(object sender, EventArgs e)
{
//this will access the Uninstall item class so we can uninstall selected item.
UninstallItem c = new UninstallItem();
c.uninstallSelectedItem();
}
Within your Form1.cs create instance of UnIstallItem class and use it. Then on Button Click call "RemoveSelected" method of UnInstaItem class by passing programsListBox to it and it should remove the selected item.
public class Form1:Form
{
ListBox ProgramsListbox;
UninstallItem unistall;
public Form1(){
InitializeComponent();
uninstall = new UninstallItem();
button1.Click+= button1_Click;
}
void button1_Click(object sender, EventArgs e){
unistall.RemoveSelected(ProgramsListbox);
}
}
Then in your external class;
public class UninstallItem{
public UninstallItem{}
public void RemoveSelected(ListBox list)
{
if(list.SelectedIndex==-1)
{
MessageBox.Show("Please Select Item from List");
return;
}
list.Items.RemoveAt(list.SelectedIndex);
}
}
The 2 easy ways to think about this are either
Call the method in your class from the event handler in your form
Have a method on your class which matches the signature of an event handler, and subscribe to the event.
The first requires no major change
private MyClass myClass = new MyClass();
public void ProgramsListbox_SelectedIndexChanged(object sender, EventArgs e)
{
myClass.DoSomething();
}
The second requires your class to have a specific method that matches the signature of that event handler currently in your form
public class MyClass
{
public void DoSomething(object sender, EventArgs e)
{
var listBox = (ListBox)sender;
// read selected index perhaps, or selected item maybe
}
}
And then in your form
private MyClass myClass = new MyClass();
protected override void OnLoad(EventArgs e)
{
this.ProgramsListBox.SelectedIndexChanged += myClass.DoSomething;
}
I have two classes, Form1.cs and secondclass.cs, I'm trying to do something on secondclass.cs and send the progress to a progress bar on Form1.cs , this is my current code:
Form1.cs
namespace DifferentClasses
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
secondclass.updateBar(20);
}
private void button2_Click(object sender, EventArgs e)
{
this.setBar(20);
}
public void setBar(int percentage)
{
this.progressBar1.Value += percentage;
Console.WriteLine(Convert.ToString(percentage));
}
}
}
secondclass.cs
namespace DifferentClasses
{
class secondclass
{
public static void updateBar(int percentage)
{
var frm = new Form1();
frm.setBar(percentage);
}
}
}
(this was a new project to test what I actually want in my main program)
as you see I have created 2 buttons, the first one runs the command via secondclass.cs
and the second one runs it directly from the same class. Funny enough both don't give errors
and both return the console line, however the first button doesn't actually change the progress bar and I can't figure out why.
The problem is in updateBar you are creating a new Form1 and setting the percentage on that.
The simplest way to solve this is to pass a reference to the current form into updateBar like this:
public static void updateBar(int percentage,Form1 f)
{
f.setBar(percentage);
}
and in the calling code do this:
secondclass.updateBar(20,this);
I'm guess the secondclass will end up running something which may take some time, so you may want to look at the async features in C#
I have a MainForm and AnotherForm. AnotherForm is accessed via MainForm's menuItem.
AnotherForm has listView. When user clicks on an item it I want to get the string element and pass it to MainForm's textbox, so the element shows there and AnotherForm is closed. So far AnotherForm closes but nothing shows in the textbox in MainForm. Any suggestions?
private void listView1_ItemActivate(object sender, EventArgs e)
{
string input = listView1.SelectedItem[0].ToString();
MainForm mainF = new MainForm(input);// called the constructor
this.Close(); //close this form and pass the input to MainForm
mainF.inputTextBox.Text = input;
mainF.loadThis(input);
}
I assume you have an instance of MainForm already, and that's what creates an instance of AnotherForm.
Inside the event you posted, you're actually creating an entirely new instance of MainForm, never showing it, and then it's destroyed anyway when AnotherForm closes.
The reason you see nothing in the text box is because you're looking at the original instance of MainForm, which you haven't actually changed.
One quickie way of fixing this would be passing a reference to the original MainForm into AnotherForm:
public class AnotherForm
{
private MainForm mainF;
public AnotherForm(MainForm mainF)
{
this.mainF = mainF;
}
...
...
private void listView1_ItemActivate(object sender, EventArgs e)
{
...
mainF.inputTextBox.Text = input;
...
}
}
Note: Instead of having AnotherForm aware of MainForm, you might want to switch it around and create a public property in AnotherForm like this:
public class AnotherForm
{
public InputValue { get; private set; }
private void listView1_ItemActivate(object sender, EventArgs e)
{
...
InputValue = input;
...
}
}
Which you can then access from MainForm when the other form is closed:
private void SomeMethodInMainForm()
{
var newAnotherForm = new AnotherForm();
newAnotherForm.ShowDialog();
var inputValueFromAnotherForm = newAnotherForm.InputValue;
// do something with the input value from "AnotherForm"
}
If your MainForm has already been created you cannot just create another one in order to access it and set properties. You've created two separate MainForms (though the 2nd one is hidden because you never showed it).
It sounds like what you want to do is a modal dialog pattern. Your MainForm is the main window in your application. You want to have a 2nd form pop up when you click on a menu link. This is called a dialog. Then when you close that dialog you want your MainForm to retrieve a value as a returned result of the dialog.
In your MainForm the event handler which handles the menu item click should look something like this:
private void pickSomethingMenuItem_Click(object sender, EventArgs e)
{
using (var picker = new PickerDialog())
{
if (picker.ShowDialog(this) == DialogResult.OK)
{
LoadSomething(picker.SomethingPicked);
}
}
}
Then the following code would be inside your dialog form:
public string SomethingPicked { get; private set; }
private void somethingListView_ItemActivate(object sender, EventArgs e)
{
SomethingPicked = somethingListView.SelectedItem[0].ToString();
DialogResult = DialogResult.OK;
}
Notice how I named all of the objects with meaningful names. Well, except for "Something". It was impossible to tell from your code what you were actually using the dialog to pick. You should always use meaningful names for your objects and variables. Your code is almost completely nonsensical.
And you should almost never make a control on a Form public like you have with your inputTextBox. You should always expose values you want to share as public properties.
On this presented solution, you could do five main things in order to achieve what you want to do, namely:
1) Declare a global object for AnotherForm in MainForm
2) Initiate a FromClosing event handler for AnotherForm in MainForm
3) Make a public property or field in AnotherForm
4) Before closing in AnotherForm you save it the public property mentioned above
5) In the MainForm get the public property from AnotherForm
Here is the code:
MainForm
public partial class MainForm : Form
{
AnotherForm anotherForm; // Declare a global object for AnotherForm
public MainForm()
{
InitializeComponent();
}
private void showToolStripMenuItem_Click(object sender, EventArgs e)
{
anotherForm = new AnotherForm(); // when Menu Item is clicked instantiate the Form
anotherForm.FormClosing += new FormClosingEventHandler(anotherForm_FormClosing); // Add a FormClosing event Handler
anotherForm.ShowDialog();
}
void anotherForm_FormClosing(object sender, FormClosingEventArgs e)
{
inputTextBox.Text = anotherForm.listViewValue; // get the Value from public property in AnotherForm
}
}
AnotherForm
void listView1_ItemActivate(object sender, EventArgs e)
{
listViewValue = listView1.SelectedItems[0].Text; // Get the listViewItem value and save to public property
this.Close(); // Close
}
public String listViewValue { get; set; } // public property to store the ListView value
One thing to note here in comparison to your code I didn't use ToString() in ListView.SelectedItems:
listView1.SelectedItems[0].ToString();
But instead use the Text Property:
listView1.SelectedItems[0].Text;
I have a program that has a parent form which then creates a child form. Upon clicking the updateButton within the child form, I want the searchButton within the parent form to fire.
However I get an error for protection reasons. I have tried setting everything Public just to see, still wont work for me.
Error 1 'SalesSystem.SystemForm.searchButton' is inaccessible due to
its protection level SalesSystem\UpdateForm.cs 111 20 SalesSystem
This is what I have so far.
Parent Code
namespace SalesSystem
{
public partial class SystemForm : Form
{
public SystemForm()
{
InitializeComponent();
}
protected void searchButton_Click(object sender, EventArgs e)
{
//search code
}
private void updateButton_Click(object sender, EventArgs e)
{
try
{
UpdateForm upForm = new UpdateForm(resultBox.SelectedItems[0].Text, dbdirec, dbfname);
upForm.ShowDialog(this);
}
catch (Exception)
{
//
}
}
}
Child Code
namespace SalesSystem
{
public partial class UpdateForm : Form
{
public UpdateForm(string selectedPerson, string dbdirec, string dbfname)
{
InitializeComponent();
}
private void updateButton_Click(object sender, EventArgs e)
{
//do stuff
SystemForm parent = (SystemForm)this.Owner;
parent.searchButton.PerformClick();
this.Close();
}
}
}
Your searchButton button control is set to private by default in WinForm. You've said you set everything to public but I assume you mean you've set everything in the code you've posted to public. There are a few ways to fix this. The direct fix would be to simply go to Visual Studio designer, select the button, and set its Modifier property to internal or public.
However, it seems you're closing your form straight after so I'd just have my parent form subscribe to the FormClosing event of the form.
UpdateForm upForm = new UpdateForm(resultBox.SelectedItems[0].Text, dbdirec, dbfname);
upForm.FormClosing += (s, o) =>
{
//your code for what the parent class should do
};
upForm.ShowDialog(this);
If you're not closing the form then you can create your own event handler that your parent form subscribes to.
You have 2 options:
create a public void search() method in your parent form. Then, instead of accessing the the button on the parent form and invoking its click event, you run the search code directly. The new method is not tied to a GUI element and accessing it from a different form is no problem.
The better solution is to create a delegate. A delegate is an execution target that will be assigned at run time. The parent form still has a public void search() method. And when it creates the child form, it will pass the name of that function as parameter. The child form has no knowledge about the parent form (as opposed to the first option where the child MUST know that there is a method called search()). When it is time to inform whoever created the child form, the delegate is called. This is a small example:
public partial class SystemForm : Form
{
public delegate void dSearch();
public SystemForm()
{
InitializeComponent();
}
protected void searchButton_Click(object sender, EventArgs e)
{
search();
}
private void search()
{
//search code
}
private void updateButton_Click(object sender, EventArgs e)
{
try
{
UpdateForm upForm = new UpdateForm(resultBox.SelectedItems[0].Text, dbdirec, dbfname, search);
upForm.ShowDialog(this);
}
catch (Exception)
{
//
}
}
}
And the child form:
public partial class UpdateForm : Form
{
private SystemForm.dSearch _target;
public UpdateForm(string selectedPerson, string dbdirec, string dbfname, SystemForm.dSearch target)
{
_target = target;
InitializeComponent();
}
private void updateButton_Click(object sender, EventArgs e)
{
//do stuff
_target();
this.Close();
}
}
You should use the "Model View Controller" or "Model View Presenter" pattern to approach this kind of thing.
Each form should only be concerned with displaying its contents to the user. When it comes to responding to UI events such as button clicks, each form (i.e. each "View") should simply raise an event which informs the controller/presenter that something has happened.
The controller/presenter should then respond appropriately. Then the logic that wires together different forms (such as the parent and child forms in your example) is encapsulated in the Controller class. Such logic does not really belong in either of the forms.
I wrote an example that demonstrates a simple design to do this sort of thing in another answer some time ago. Rather than copy/paste it all here, I'll just give you a link to it:
How to make Form1 label.text change when checkbox on form2 is checked?
You'll have to scroll down to see my answer. It's broadly similar to what you're doing; hopefully it will make sense to you! Follow the instructions to make a test application and run it to see what happens.
I'm tired and might be missing something but that is correct behaviour.
Your child form does not directly inherit from your parent form.
Your parent form has a protected level, so only it and classes that extend it can access the method.
2 solutions:
Change your child form to:
public partial class UpdateForm : SystemForm
Change method to public
public void searchButton_Click(object sender, EventArgs e)
You could expose a Search Event from your UpdateForm and subscribe to this event in the SystemForm
namespace SalesSystem
{
public partial class SystemForm : Form
{
public SystemForm()
{
InitializeComponent();
}
protected void searchButton_Click(object sender, EventArgs e)
{
//search code
}
private void updateButton_Click(object sender, EventArgs e)
{
try
{
UpdateForm upForm = new UpdateForm(resultBox.SelectedItems[0].Text, dbdirec, dbfname);
upForm.OnSearch += Search;
upForm.ShowDialog(this);
}
catch (Exception)
{
//
}
}
private void Search(string searchParameter)
{
....
}
}
namespace SalesSystem
{
public delegate void SearchEventHandler(string searchParameter);
public partial class UpdateForm : Form
{
public event SearchEventHandler OnSearch;
public UpdateForm(string selectedPerson, string dbdirec, string dbfname)
{
InitializeComponent();
}
private void updateButton_Click(object sender, EventArgs e)
{
//do stuff
OnSearch("SearchThis");
this.Close();
}
}
}
I have "formA" and 2 buttons on it (button1 and button2). What I want to do is:
When I click on button1 to call "formB" display text written in label1.
When I click button2 to call the same form ("formB") hide label1 and display label2.
The problem is that I don't know how to check what button is clicked on "formA".
Edit: Thanks very much folks for the quick answer. Problem is solved!
This is where events come in handy:
public class FormA
{
private void button1_Click(object sender, EventArgs e)
{
formB.Button1WasClicked();
}
private void button2_Click(object sender, EventArgs e)
{
formB.Button2WasClicked();
}
}
public class FormB
{
public void Button1WasClicked()
{
label2.Visible = false;
label1.Visible = true;
label1.Text = "Button 1 was clicked!";
}
public void Button2WasClicked()
{
label1.Visible = false;
label2.Visible = true;
label2.Text = "Button 2 was clicked!";
}
}
button1 and button2 have their own separate Click event handlers. This way we can differentiate the two when they are clicked.
If you have the same event handler for both buttons (as mentioned in one of the comments), you can identify them with the sender parameter using:
Object.ReferenceEquals(sender, button1);
or
Object.ReferenceEquals(sender, button2);
Then your code would look like this:
private void button_Click(object sender, EventArgs e)
{
if (Object.ReferenceEquals(sender, button1))
{
formB.Button1WasClicked();
}
else
{
formB.Button2WasClicked();
}
}
FormB can't find out, the buttons are a private implementation details of FormA. They might not even be a button, surely you are going to add a menu or a toolbar to FormA some day.
The workaround becomes much simpler if you stop thinking of "calling a form". You never call a form, you create an instance of it. And then you make it visible by calling its Show() method. Lots of things you can do in between those two steps.
Add a public method to FormB. For lack of a better name:
public void MakeLabel2Visible() {
this.label1.Visible = false;
this.label2.Visible = true;
}
Now it becomes simple. Implement button2's Click event handler like this:
private void button2_Click(object sender, EventArgs e) {
var frm = new FormB();
frm.MakeLabel2Visible();
frm.Show();
}
Adding another constructor to a form that lets you initialize it differently is another very common approach. These are just classes, standard programming techniques are appropriate.
Because you are using winforms you can do all this very easily due to the fact that you have a stateful environment.
Assuming a very basic set up with:
event handlers in the code behind of form a
a reference to an instance of form b in form a (or the button click creating such an instance)
a method to use in form b to pass it data
Your code will be something like this:
public partial class FormA : Form
{
private FormB formB;
public FormA()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
if (formB == null || formB.IsDisposed)
{
formB = new FormB();
}
formB.UpdateLabel("Button A");
formB.Show();
}
private void button2_Click(object sender, EventArgs e)
{
if (formB == null || formB.IsDisposed)
{
formB = new FormB();
}
formB.UpdateLabel("Button B");
formB.Show();
}
}
public partial class FormB : Form
{
public FormB()
{
InitializeComponent();
}
public void UpdateLabel(string message)
{
label1.Text = message;
}
}
Of course, there are lots of improvements to this - using events and alerts more intelligently and refactoring to remove duplication, but this is a basic example of the sort of things you can do.