I'm trying to do the following:
I have a form1 with a textBox and the following method:
public void ChangeText()
{
textBox.Text = "A";
}
The application runs a form of class Form1 - We'll call it mainForm.
That main form starts another process that creates another form of class Form1 - Let's call it childForm.
I now want to click a button on mainForm and have the childForm's ChangeText() method called so that the childForm's textBox is the one that is effected.
I've been looking for a while and I can't seem to make it work. I'm not entirely sure it's even possible.
API doesn't seem to give me the option at all and with WCF the method is being called, but the original form is not recognized.
Sure, it's possible, but since the two forms are in different processes, you'll need an inter-process communication (IPC) mechanism like .NET Remoting or Windows Communication Foundation. Or you can use this technique.
Assuming you want to edit logic on the way
--
If mainForm instantiates childForm then it should also hold a reference to it.
i.e. private Form childForm = new Form();
Call mainForm.ChangeText() which will look something like this (this gets called by the event so the parameters will in fact be the event and sender parameters):
public void ChangeText(EventArgs e, Sender sender)
{
this.childForm.ChangeText(EventArgs e, Sender sender)
}
You can also access the textBox directly if you make it public
i.e.
this.childForm.textBox1.Text = text
Corrected accessor mistake as pointed out by another user
Related
I have a custom control that I'm also using as a DataGridView control. This custom control has a method called SetHttpClientand I pass a HttpClient object as parameter.
How can I call this method from the parent form? (The parent form only knows about the instance of the class deriving from DataGridViewTextBoxCell)
You should build a nice structure for this. For example if you have two Forms, and in Form 1 you have the Grid, which you want to refresh From Form 2. If you want to open Form 2, you should pass the instance of the Grid from on creating the instance.
Or a second way, Form 2 provide an event which will be subscribed in Form 1. And the event is called if the Grid should be refreshed. You can than pass the HttpClient over the Args-Object to Form 1.
Please tell me, if i misunderstand you.
In my opinion you should use a ViewModels to communicate with View instead of one View execute action on second View.
So, for example your View like
CustomersView contains CustomersViewModel in DataContext, if you execute a operation GetData you make it in CustomersViewModel and the result put to DataGridView.
This solution moves responsibility of providing data from class DataGridView to CustomersViewModel. The ViewModel can use some Service or other mechanism to provide you data using HttpClient.
I know that's not straight answer for your question, but is good solution for your problem.
In this example https://msdn.microsoft.com/en-us/library/ff798384.aspx you have method GetParts, you can imagine that the body of this method contains HttpClient and get the data from a website.
May be you're talking about access modifiers like private, public, internal.
If so, then in child form make access modifier like public or internal.
And in parent form just make needed call.
public partial class ChildForm : Form
{
public ChildForm()
{
InitializeComponent();
}
internal String HellowWorld_mt(string SuffixValue)
{
return "hello world and "+ SuffixValue;
}
}
public partial class ParentForm : Form
{
public ParentForm()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
ChildForm cf = new ChildForm();
cf.Show();
string resp = cf.HellowWorld_mt(" extra!");
this.Text = resp;
}
}
More about that: Access Modifiers (C# Reference)
I'm having some problems with my form and the business class:
The form does not open until the business class has finished it's work. Every time I call Form1 in Main(), Form1 calls two methods:
InitializeComponents();
testConnection();
testConnection calls the business class and sets the properties of the Form according to the properties of the business class. Like that:
Pingger pingger = new Pingger();
ipLabel.Text = pingger.getLocalIP();
I do not do just these operations, I also do others like the result of a ping. However, Form1 takes a long time to open and when it's open Form1 shows the results. What do I have to do, create Form1, open it, and then after 3 seconds start to process the business class?
What you want is an event raised by your form control. To determine if there is such an event you simply Google the class (ie Form). On the msdn page every property, method and event is listed accompanied with what they do.
What you want is the Shown event. You can add an event to this and then handle whatever it is you want to do. See link below.
http://msdn.microsoft.com/en-us/library/system.windows.forms.form(v=vs.110).aspx
You can subscribe to the Shown event for the form and call your testConnection() method from there.
InitializeComponents();
Shown += (s,e) => testConnection();
You could also use multi-threading to "launch" the testConnection() method. (but then you have the added complexity of making sure the results are in before you rely on them, thread safety, etc...)
I wonder you want to show the form just before the connection is tested?
The idea could be using multi-threading like the Wonderbird suggestion, using some like this:
InitializeComponent();
new Thread(testConnection).Start();
I'm trying to show a Form before an application's start and get its DialogResult, so I'm just creating it and using ShowDialog (because Application.Run's return value is void).
What I'm worried about is that it might get 'hijacked' by mistake by some other Form that might be shown at the time. Not by this application, obviously. See What is the meaning of Form.Show(null)? that it's not advisable to use the parameterless overload of ShowDialog.
I have tested and seen that the Form's Owner property was null. But will it always be so? Or should I create a Form and use that as the Owner without showing it? That seems a strange solution but logically it should avoid any problem. Or will that introduce new ones?
Not by this application, obviously
This is already taken care of by Windows, it enforces a strong separation between processes and windows owned by threads. A typical choice for the owner of a dialog for example is the window returned by GetActiveWindow(). The active window is a property of a thread. Which explains for example why a MessageBox.Show() call made from a worker thread is never modal to the rest of the windows.
Making a window modal against the windows of another process is technically possible but requires lots of effort. The app would have to call AttachThreadInput(), a very unsubtle winapi function that nobody ever calls by accident. Also a great source of deadlock.
Unless you are programming in a boat near the Somali coast, there is no good reason to fear your window getting hijacked.
[STAThread]
static void Main()
{
Form1 form1 = new Form1();
//here I suppose the form you want to show
Form1 form2 = new Form2();
form2.ShowDialog(form1);
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(form1);
}
Basically you use ShowDialog() when there are no parents for this window. Usually this happens for the main window. If you are opening one window after another, while closing previous, then there will be multiple ShowDialog()s.
If you are showing dialog (which is also a window), then you can specify it's parent to achieve a certain behavior. To example, when alt-tabbing to that window, it's dialog will be shown in front. Think about this as making child-parent relations.
I don't know about the case, when multiple forms are the claiming same parent. But it sounds like a clear mistake, to example:
public Form1 FormMain = new Form1();
...
// show main form
FormMain.ShowDialog();
...
// somewhere in the main form - show dialog
Form2 form2 = new Form2();
form2.ShowDialog(FormMain);
...
// somewhere in form2 - show dialog
Form3 form3 = new Form3();
form3.ShowDialog(FormMain); // wrong, should be form2!
This is not tested because I couldn't recreate a case where the parent is ever anything but null (i.e. a reference to a third-party un-managed parent), but maybe you could do something like this on your form to set the parent to null if it changes:
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
this.ParentChanged += MyParentChanged;
}
public void MyParentChanged(Object sender, EventArgs e)
{
this.Parent = null;
}
}
I have this battleship program where i am trying to access a function in another form. This function is used to change the buttons on the game board to either enabled or disabled, depending on who's turn it is. Changing the buttons to enabled and disabled is not my problem. My problem is accessing the function to do it in the other form. I would post code, but it is lengthy and spread between three forms.
Appreciate any help!
Thanks in advance!
Luke
Why not pull the functionality out into its own public class (like ButtonConfigurator or something like that). Then any form can hold a ButtonConfigurator object and use it.
It depends on your code architecture:
Kind of rough one: If you just have several forms Form _form1, Form2 _form2, you can create kind of relationship between them, by, just an example pseudocode:
public class Form1:Form
{
Form2 _form2Object = null;
public Form1(Form2 frm2)
{
_form2Object = frm2;
}
//and after when needed just use that _form2Object to call a mehod on it.
}
More nice one: is declare shared between all your forms event Dispatcher. So when Form1 wants to notify somethign to Form2 it calls Dispatchers relative method, which takes care to call right method on Form2
There could be a lot of other solutions more or less nicer, but it strongly depends on your app architecture. Here I just put down a couple of choices you could have.
Hope this helps.
Regards.
you need pass the instance of the form with Button to the form you call the function, make the function public.
Lets suppose you have a Form form1 which has method method1, that you want to access in Form form2. You could declare that method as public static. This way you could access that method like form1.method1.
Situation: C#, .NET 3.5, WinForms
Objective: Form1 has a Button that can be enabled via the constructor. I.E. the button will only be shown if I call new Form1(true).
We'd like to be able to pass a method via some param from Form2 to Form1 (doesn't have to be on Form1's constructor), and when Form1.Button1 is pressed, Form2.<SomeMethod> should be executed.
We know that we could create a Delegate/Event in Form1 and from Form2 do something like:
Form1.SomeDelegate += new ..... (MyMethodInForm2);
…and then in Form1_ButtonClick we fire the event which, in turn will do the magic in Form2.
But we were wondering if there was a more elegant/new/modern version (Anonymous Methods? Lambda Expressions? Etc.) to accomplish this.
The idea is that "any" form could instanciate a Form1 class and pass its own method to be executed when Form1's button is clicked; but instead of a callback to the caller (form2,3,..n), Form1 executes the passed function (which possibly resides inside the caller). We really don't need these functions to have parameters for now.
Note: The code samples contain simple variable/object names and are not taken from real life, please ignore the simplicity.
UPDATE Sorry for not being more specific, I think that I'll keep using the Delegate/Event model, but for reference, here's what I think is a better description of the situtation:
Form1 is a generic form, that accepts a list of items and displays them. We may pass Employee types or Person Types or any "T". It works ok.
We received a requirement from a customer, asking if it was possible to add an optional button to that little Form1 that, if clicked, it will open another form/execute some method.
That way, if I am using Form1, I could -at runtime- tell the button to open the EmployeeForm, whereas if I am using Form1, the very same button could open the form PersonForm. Now opening a Form is not the only use we'd have for that button, but that's the caller's problem.
Right now, what I've done is what we've said: delegate/event on that Form1 and on the "calling" form we do a Form1.theEvent += stuff, to subscribe to the event. I just wanted to know if there was a better way to accomplish this, as this is how we'd do it in .NET 2.0 and we have just started using .NET 3.5.
It sounds like you're describing the same thing twice.
Subscribing to an event does exactly this - passes a function to Form1, which then executes the function when the event is raised.
You could subscribe to the event using a lambda expression if you want, but you don't have to.
Of course you could put the delegate as a Form1 constructor parameter if you wanted, but I don't see much advantage to doing so in this case.
In short: I think normal events do everything you need. If you have a requirement which events don't handle, please give more information.
Not totally sure what you mean with the form stuff, but you can send in a Func. For example:
public class MyForm<T>
{
private readonly Func<T, bool> predicate;
public MyForm(Func<T, bool> predicate) { this.predicate = predicate }
private void SomeMethod()
{
bool result = predicate();
// Do something
}
}
var form = new MyForm(x => x.Number < 5);
1st:you should declare a public event in Form1.
2nd:you should invoke the event where it is sent to Form1 like Button1_Click
From what I can tell, Form2 is a non-modal dialog that Form1 can update. However Form2 might not have been created yet.
The obvious way to accomplish updating Form2 is using the event model as you have, using Composition and passing Form1 into its constructor.
You could use a delegate and store that but I can't see how that is preferably to passing a reference to the parent Form in.
If you want Form2 to update any type then a simple interface would solve the problem.
Another approach is to expose the Click event of the button by defining a "proxy-event" on the generic form:
public class MyForm<T> : Form
{
public event EventHandler MyClick
{
add { this.theButton.Click += value; }
remove { this.theButton.Click -= value; }
}
// ...
}