C# Passing control reference to another form - c#

I have a button and hidden textbox on my main form. When I press the button it will hide the main form and show the second form. When I press the button on the second form I want to show the main form again but this time I need to show the hidden textbox. I know how to pass the text from a textbox to another form but not just the reference of the textbox.

You better pass the complete main form instance for the second form, and create a public function to set the textbox to visible, or create a property around it.
Something like:
//form1
Form2 second = new Form2(this);
}....
public void ShowTextBox()
{
textbox1.Visible=true;
}
//form2
Form parent;
public Form2(Form _parent)
{
parent=_parent;
}
///later
parent.Show();
parent.ShowTextBox();

Sounds to me like a custom event would be a better approach. Have the secondary form expose an event, which is raised at whatever appropriate time (your button press). In your main form, when you create your instance of your second form, subscribe to that event. Then run your "unhide" code from within the mainform's event subscription.
This keeps the coupling down on the two forms and results in much more easily maintainable and extensible code (for best effect, use interfaces, but events are a good middle ground for learning).
Something like this:
(it's been a long time since I worked with winforms, or events even, so if this needs refining let me know)
// your secondary/popup form's class
public partial class Form2 : Form
{
// add a custom event
public EventHandler<EventArgs> MyCustomEvent;
// link up your button click event
void InitializeComponent() {
myButton.Click += myButtonClick;
}
// when your button is clicked, raise your custom event
void myButtonClick(object sender, EventArgs, e) {
onMyCustomEvent();
}
// this "broadcasts" the event
void onMyCustomEvent() {
EventHandler<EventArgs> h = MyCustomEvent;
if (h != null) {
h(this, new EventArgs());
}
}
}
// your main form's class
public partial class MainForm
{
void InitializeComponent() {
// ...
}
void showForm2() {
var form2 = new Form2();
form2.MyCustomEvent += form2CustomEvent;
form2.Show();
}
void form2CustomEvent(object sender, EventArgs e) {
myHiddenTextBox.Visible = true;
}
}
All in all this is a much better approach in terms of code architecture. Now the popup doesn't care who opens it (it has no reference to the main form), and the custom event (which is really what you're after) can be managed to any level of control you need, without interfering how other thing work (for example, perhaps later you may want to have a different action that fires this same custom event...)
Food for thought.

Related

How do I make a class in c# so I can click a button on 1 form to update data on a second form?

I am currently making an rpg using Winforms for a school project. However my knowledge on classes is so limited that I'm having trouble making a proper class that takes in data from 1 form, is used in the second form, then sent back to the first form.
The process I'm trying to accomplish is like this:
main form opens a second form that displays items in a listbox.
1
when you select an item and press a button to use it, the items effects are applied.
2
The data for the effect is in the first form where many other calculations are made with the same data.
3
I keep running into the problem of making a new object of a class and the data from the first form is reset. How would I go about either using an existing object from the first form, or creating a reference class maybe?
This is the function I want to run on the first form when the button on the second form is clicked.
public void SmallPot()
{
currentPHP += pHP * .25;
if (newPHP > pHP)
{
newPHP = pHP;
}
pHPBarUpdate = (int)(newPHP / pHP * 377);
pnlCurrentPHP.Width = pHPBarUpdate;
newPHP = currentPHP;
}
Expected:
When I click the use button on the popup form it closes and the items effects are displayed on the Main form.
What Happens:
Since I create a new object of form one in form two, all my variables are reset to 0 before the calculation, resulting in nothing happening after the second form closes.
I will give you a general guideline to implement a solution based on event definition and raising
Let's start from your second form where you need to communicate to the first form the event
public class Form2 : Form
{
// start creating the delegate type
public delegate void OnItemSelected(string itemName);
// declare the public event that this form will raise
public event OnItemSelected ItemSelected;
protected void cmdItemUse_Click(object sender, EventArgs e)
{
// When the user clicks to select an item....
string itemName = GetItemSelectedFromList();
// Check if someone is interested in this item selection
if(ItemSelected != null)
ItemSelected.Invoke(itemName);
}
}
Now we change something in the first Form. We need to create the second form and before displaying it we subscribe to the event exposed by the second form
public class Form1 : Form
{
... other stuff....
protected void cmdOpenSelection_Click(object sender, EventArgs e)
{
using(Form2 frm = new Form2())
{
// Subscribe the event giving it a method inside this class
// that doesn't return anything and receives a string
// as required by the delegate type of the event
frm.ItemSelected += handleItemSelection;
frm.ShowDialog(); // frm.Show();
}
}
private void handlerItemSelection(string itemName)
{
// This method is a custom Event handler and inside Form1
// will be called by Form2 through the Invoke on the event variable
}
}
In the example above I choose to pass a simple string, but of course you could pass anything including a reference type like an instance of a class containing all the info
required by the Item selection.

check whether a button in another window is clicked

I want to open a window if a button is clicked, and that button is located in another window.
So how to check whether a button in another window is clicked or not?
Now I am coding in a class called 'RightButton.cs'
I want to open a window called 'PopUp' when 'Add' button in 'Reason' window is clicked.
PaidOutReason paid = new PaidOutReason(trnprt, apiParameters);
paid.ShowDialog();
if (paid.btnSave.ClickMode == new ClickMode())
{
PopUpBanks popu = new PopUpBanks(this);
popu.Show();
}
This one was working perfectly, but I had to remove ShowDialog() and replace it with Show(). Then it was not working.
This is for a POS system. It has a user Control called 'Keyboard'. When the 'Reason' window is opening this Keyboard also want to be opened. Therefore I had to replace ShowDialog() with Show().
I'd add an event to the window, and bind an event handler to it.
class WndWindow{
BtnPaid_Click(object sender, EventArgs e){
using(var paid = new PaidOutReason()){
paid.BtnAddClick += Paid_BtnAddClick;
paid.ShowDialog();
paid.BtnAddClick -= Paid_BtnAddClick;
}
}
Paid_BtnAddClick(object sender, EventArgs e){
var popu = new PopUpBanks();
popu.Show();
}
}
class PaidOutReason{
public event EventHandler BtnAddClick;
BtnAdd_Click(object sender, EventArgs e){
//Do standard event handler code
BtnAddClick?.Invoke(this, e);
}
}
If there's any sort of checks you need to perform you can do that before reading the event, and simply return if checks fail.
You can use static controlls in your app. Start with declaring static window object in App.xaml.cs, for example
public static PaidOutReason paidOutWindow;
then, in App constructor method, after InitializingComponent(), initialize static window class:
paidOutWindow = new PaidOutReason();
You may wonder what it gives to you. Since it's POS application, you are likely to use the same set of windows quite often and repeatedly, means you can hold window object in memory and refer to it (and change, when needed). Also, after doing such thing, you will have access to all structures inside PaidOutReason object, by typing
App.paidOutWindow.FunctionName();
and finally, you should have access to all window functions such as ShowDialog().
If you are using MVVM pattern, then you can use command binding for showing the PopupBanks window.
For example:
public class ViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public ICommand AddCommand { get; set; }
public ViewModel()
{
AddCommand = new RelayCommand(AddCommandHandler);
}
private void AddCommandHandler()
{
IPopUpBanks popu = new PopUpBanks(this);
popu.Show();
}
}
PaidOutReason view:
1. <Button x:Name="Add" Command={Binding AddCommand}/>
2. Set the above viewmodel as datacontext of PaidOutReason view.
Create a interface IPopUpBanks containing Show() method and implement this interface on PopUpBanks view.
Handle the Click event of btnSave:
PaidOutReason paid = new PaidOutReason(trnprt, apiParameters);
paid.btnSave.Click += (ss, ee) =>
{
PopUpBanks popu = new PopUpBanks(this);
popu.Show();
};
paid.Show();
Instead of the Keyboard Window, I made it a user control and then initialized an event in there. Then I insert that Keyboard User Control to the PaidOutReason Window and then called the event. Then I was able to use ShowDialog() to call the window.

Reloading the form instead of making a new one / accessing textbox outside of form

I am having a problem controlling a textbox. I need to change a value from outside of Form1.cs where the textbox is located for this I have found this snippet.
public void UpdateText(string newValue)
{
torrent_name0.Text = newValue;
}
this allows me in theory to control the textbox outside of Form1.cs, but here comes the problem, every time I want to access it I create a new instance of Form1 instead of using the old one and refreshing it.
Form1 frm = new Form1();
frm.UpdateText("aaaaaaaaaaaa");
frm.Show();
am I missing something? is there a better way to do this? I have tried multiple ways to update the new form but got nowhere.
Bokker,
You will have to have a reference to the singular form1 to which all things refer.
If this is a child form, then as Aybe commented, create a public member of your mainform and name it something.
Public Form myForm1;
You probably have some Event by which you would like Form1 be launched...
A Button click, menu item, toolbar item, etc. In that event you will have to check if the form exists and create if required.
private SomeEvent() {
if (myForm1 == null)
{
myForm1 = new Form1();
myForm1.Show(this);
}
myForm1.UpdateText("some text");
}
Alternatively, you could create the form in the Form Load event, just so long as you create the form prior to attempting the myForm1.UpdateText()
If you follow this paradigm, you are creating myForm1 as part of the main form, best practice says you should also dispose of the form in your main form Closing Event.
private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
{
if (myForm1 != null)
{
myForm1.Close();
myForm1.Dispose();
}
}
This is all off the top of my head, so it might not be perfect.
In that case you can pass the instance of form in the method as argument and make the changes like
public void UpdateText(string newValue, Form1 frm)
{
frm.torrent_name0.Text = newValue;
}

Custom event handling

I have mainVariable.cs that contains delegates for events. Also I have several forms and a worker.cs. My problem is that Login form is starting form and handles some event. After that it hides itself and shows another form. Now the problem starts here, because second form which started after login, cant handle any events. I mean when I raise an event from worker.cs and login form handles the event not the second from even if I dispose the login form. How can I solve this puzzle ?
Apply this to your Programm.cs
Application.Run(loginForm);
if (loginForm.IsLoggedIn == true)
{
ERS_FDData.ERSUser user = loginForm.user;
loginForm.Close();
Application.Run(new frmMain(loginForm.user));
}
else
Application.Exit();
After the login is done, you need to set the Mainf Frame to be the application default window
For any event to be handled you need to assign it a subroutine.
You can do this from any form, given you initialize and show it first.
For example.
Form1
{
FormLoad()
{
mybutton.click += new EventHandler(myfunction);
}
myfunction(object o, EventArgs e) { // Dostuff }
}
So you'd initialize Form1 something like this
Form1 myform = new Form1();
And the event will work as the form expects.

Show/Refresh Button working properly

I have a checkbox in form1, when it is checked it makes a PictureBox in form2 visible but when I uncheck I want to refresh form2 so that the PictureBox is not visible. This code is in form1. It is a button that opens up the form if one if not open but if a form is open it refreshes it. The problem is that it is not refreshing. Can anyone tell me what is wrong?
private tuesday _FavoritesForm;
public void startbutton_Click(object sender, EventArgs e)
{
if (_FavoritesForm == null)
{
_FavoritesForm = new tuesday();
_FavoritesForm.Closed += new EventHandler(_FavoritesForm_Closed);
_FavoritesForm.Show();
}
else
{
_FavoritesForm.Refresh();
}
}
Calling Refresh on a form merely forces it to be repainted. There isn't any reason to assume that it will repaint differently. You would have to override the OnPaint() method in that form. Clearly you are not using OnPaint to draw an image, you are using a PictureBox. Setting that control's Visible property to false will make the image disappear, no additional help is needed.
I would add a public method on the secondary form to Show/Hide the picture because it appears the second form has no idea of the first form. Then the click / checkbox setting on the first form to instead of doing a "REFRESH" on the second, create the form if its not already done so. Once created, call whatever method you expose on the secondary form to specifically make visible or not as needed.
EDIT FOR CLARIFICATION
#a13xy, actually the reverse... The second form has no idea of the first, but yes, have a method that is public on the 2nd. Then on the FIRST form, in the click / value changed event of your checkbox, you just call the method from that... such as your sample code...
public void startbutton_Click(object sender, EventArgs e)
{
if (_FavoritesForm == null)
{ _FavoritesForm = new tuesday();
_FavoritesForm.Closed += new EventHandler(_FavoritesForm_Closed);
_FavoritesForm.Show();
}
else
{ _FavoritesForm.Refresh();
}
_FavoritesForm.ShowHide( IsCurrentForms.CheckBox.IsCheckedValue );
}
Not positive of your checkbox controls name, or its Checked value property, just call the second form's method directly with whatever your forms value is and the method in the SECOND form could be something like...
public void ShowHide( Boolean ShowTheImage )
{
// value provided as a direct parameter from the first form,
// THISform knows about its own Picture property and can directly
// set the visibility within its scoped control.
this.YourPicture.Visible = ShowTheImage
}

Categories

Resources