473,387 Members | 1,516 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,387 software developers and data experts.

How to call an event on another form - C# windows forms

I don't think this should be this complicated, but I can't figure it
out. I've worked with C# for several years now, but in a web
environment, not with windows form. I have a form with a query button
on it. If the query returns multiple results, a new window is opened
with a grid containing the results. When the user double clicks on
the desired row in the grid, I want the first form to populate with
the correct data. I don't know how to access that other form.
Basically on the double click event, I think I need to call an event
on the other form. How do I do that? A friend that has worked with
windows forms before in VB showed me the WithEvent stuff, but C#
doesn't have that. This form are MDI forms as well - which I am not
familiar with, but both of the forms are children - not the parent.
Any help is greatly appreciated!

Thanks

Jen

May 21 '07 #1
8 36029
On Mon, 21 May 2007 12:56:24 -0700, <ho*********@gmail.comwrote:
[...] If the query returns multiple results, a new window is opened
with a grid containing the results. When the user double clicks on
the desired row in the grid, I want the first form to populate with
the correct data. I don't know how to access that other form.
Basically on the double click event, I think I need to call an event
on the other form. How do I do that? [...]
You need a couple of things: some sort of reference back to the form you
want to update, and some sort of mechanism to accomplish that update.

The most direct method is to access an actual reference for the calling
form in the results form, and have that results window directly access the
fields on the original form that you want to update. There are at least
three variations on this, all somewhat "clunky":

1) Access your calling form directly by name. Eg "form1". Nice and
simple. Not very extensible, but it'll get the job done.
2) Access your calling form by type, passing the form instance
reference to the results window constructor or other mechanism (setting a
property after construction for example). Almost as simple as #1, you can
still access controls by field name, but can be extended to any instance
of the calling form (that is, any form with the specific type).

Note that in 1 and 2, the controls in your form need the access modifier
to be changed to public so that the results form can see them.

3) Access your calling form's control by name, using the
ControlCollection.Find() method to get the controls. Icky-pooh! :) If
you're going to do something like this, IMHO you might as well just define
an interface that the query form exposes, because it's just as much work
and at least an interface is something that can be verified at compile
time.

I don't know what the VB "WithEvent stuff" does, but assuming it's similar
to C# events, then that's actually a better, more-maintainable solution.
You can declare an event on the results form, and then the form with the
query button on it can subscribe to the event. The event would be
designed to allow passing the interesting data back from the results form
to the query form. When the query form's event handler is executed it
would then update the query form directly.

For example:

class Results : Form
{
public delegate void DoubleClickHandler(ResultsData data);
public event DoubleClickHandler DoubleClick;

// Hooked to the double-click event of the grid
void grid_DoubleClick(object sender, EventArgs e)
{
DoubleClickHandler handler = DoubleClick;

if (handler != null)
{
ResultsData data = /* initialize results data to be passed
to calling form */

handler(data);
}
}
}

class Query : Form
{
void buttonQuery_Click(object sender, EventArgs e)
{
Results results = new Results();

results.DoubleClick = HandleResultsDoubleClick;
results.ShowDialog();
}

void HandleResultsDoubleClick(ResultsData data)
{
// extract information from "data" and fill in form
appropriately
}
}

The above assumes you've declared some "ResultsData" data structure
(struct or class, as appropriate) that can contain the data you want to
pass. You don't really have to do that though...you could just pass each
piece of data as an individual parameter in the event.

Note that the results form in this case needs to know exactly *nothing*
about the calling form. The results form declares a standard event that
any caller can subscribe to, and it's up to the caller to process that
event in some way that makes sense to itself.

The above is just an example. The specifics will vary according to your
needs. The key thing is to define the delegate, event, and event handler,
to hook the event handler up in the query form, and to call it at the
appropriate time in the results form.

Some people may complain that I didn't use the standard "(object sender,
EventArgs e)" parameter list used by the standard control-style events. I
think those are fine for the standardized events, but for a custom eventI
don't see the point, _unless that pattern actually fits well in your
design_. For example, your query form needs to know which form is
signaling the event, then you'd want to include an "object sender"
parameter.

Finally, I'll mention that you can also accomplish this by defining an
interface that the calling form is required to implement. As with the #2
solution in the "direct method" described above, you'd pass a reference to
your calling form to the results form. You can use an interface in a
similar way to the events. For example, defining a single method that
takes a ResultsData instance as a parameter and having the results form
call that method. The constructor or property on the results form that is
used to pass the interface could just use the interface type rather than
the original form type.

For example:

class Results : Form
{
public interface IDoubleClick
{
void HandleDoubleClick(ResultsData data);
}

public IDoubleClick DoubleClick;

// Hooked to the double-click event of the grid
void grid_DoubleClick(object sender, EventArgs e)
{
ResultsData data = /* initialize results data to be passed to
calling form */

DoubleClick.HandleDoubleClick(data);
}
}

class Query : Form, Query.IDoubleClick
{
void buttonQuery_Click(object sender, EventArgs e)
{
Results results = new Results();

results.DoubleClick = this;
results.ShowDialog();
}

void HandleDoubleClick(ResultsData data)
{
// extract information from "data" and fill in form
appropriately
}
}

This allows different forms to support the same interface and in some ways
is no different than providing an event handler. The main difference
being that if you use an event, it is trivial to attach multiple event
handlers to the event. An interface reference provides no such
functionality; if you wanted to support multiple event handlers, that
would have to be done explicitly.

Pete
May 21 '07 #2
What instantiates and displays the two forms? That object should act as a
proxy of information or objects so that one form can "see" the other,
whether by passing a reference of one form to the other, or by implementing
event handlers itself.

Jon

<ho*********@gmail.comwrote in message
news:11**********************@u36g2000prd.googlegr oups.com...
>I don't think this should be this complicated, but I can't figure it
out. I've worked with C# for several years now, but in a web
environment, not with windows form. I have a form with a query button
on it. If the query returns multiple results, a new window is opened
with a grid containing the results. When the user double clicks on
the desired row in the grid, I want the first form to populate with
the correct data. I don't know how to access that other form.
Basically on the double click event, I think I need to call an event
on the other form. How do I do that? A friend that has worked with
windows forms before in VB showed me the WithEvent stuff, but C#
doesn't have that. This form are MDI forms as well - which I am not
familiar with, but both of the forms are children - not the parent.
Any help is greatly appreciated!

Thanks

Jen

May 21 '07 #3
<ho*********@gmail.comschrieb im Newsbeitrag
news:11**********************@u36g2000prd.googlegr oups.com...
>I don't think this should be this complicated, but I can't figure it
out. I've worked with C# for several years now, but in a web
environment, not with windows form. I have a form with a query button
on it. If the query returns multiple results, a new window is opened
with a grid containing the results. When the user double clicks on
the desired row in the grid, I want the first form to populate with
the correct data.
I'd recommend, that the first form opens the sencond with ShowDialog. The
second Form then will be modal, and the method calling the ShowDialog will
wait until the modal form closes.
The dialog form should have one or more properties, exposing the selected
data. The calling form then can read this properties and populate itself.

By examining the return value of the ShowDialog value or DialogResult
propoertie of the modal form, the calling form can detect, wehter the user
actually selected something or not. The modal form would communicate this by
setting its own DialogResult property, wich autmotically closes the form.

You will have to call Dispose on that modal form or use using, since a form
opend by ShowDialog isn't disposed while closing.

hth
Christof
May 22 '07 #4
On May 21, 8:56 pm, hoofbeat...@gmail.com wrote:
I don't think this should be this complicated, but I can't figure it
out. I've worked with C# for several years now, but in a web
environment, not with windows form. I have a form with a query button
on it. If the query returns multiple results, a new window is opened
with a grid containing the results. When the user double clicks on
the desired row in the grid, I want the first form to populate with
the correct data. I don't know how to access that other form.
Basically on the double click event, I think I need to call an event
on the other form. How do I do that?
You can't *call* an event - events themselves just allow you to
subscribe to them and unsubscribe from them. What you need is for the
owner of the event to provide a means (eg a method) which will raise
the event for you when you call it.

See http://pobox.com/~skeet/csharp/events.html for more information.

Jon

May 22 '07 #5
Wow. I am totally confused. I appreciate all the replies, but I
still can't figure this out. Maybe if I put in part of my code that
will help? I understand the whole WithEvent in VB, even though I have
never programmed in VB! All I want is when the grid_doubleClick
occurs on QueryResults, to populate the data on frmWaypts. Why is
that so hard? In a C# web application that would be no biggie. I
tried the ShowDialog like someone suggested, but then I have top-level
form parent issues! Again, I never worked with MDI parent-child stuff
before either! So that makes no sense to me either.
My Waypts form looks like this:

public class frmWaypts : System.Windows.Forms.Form
{
public frmWaypts()
{
InitializeComponent();
}

public frmWaypts(string[,] sPKeys, SqlConnection dbCn)
{
//Constructor when Modifying a Runway
//keep primary keys & values
InitializeComponent();
sArrWptKeys = sPKeys;
Wpt = new clsWaypoints(dbCn,sArrWptKeys);
dbConn = dbCn;
}

private void btnQuery_Click(object sender, EventArgs e)
{
//just putting the important pieces here. . .
frmQueryResults newFrmQueryResults = new
frmQueryResults(dtResults, clsDBQC.tWayPt, clsQB, dbConnect);
newFrmQueryResults.MdiParent = this.ParentForm;

//some if. . .else stuff going on
else
{
newFrmQueryResults.Show();
}
}
}
Now the results screen is this:

public class frmQueryResults : System.Windows.Forms.Form
{

public frmQueryResults(DataTable dt, string sFrmType,
clsQueryBuilder clsQBuilder, clsDBConn DBConn)
{
InitializeComponent();

//keep query results table
dtResults = dt;

//bind table to grid
ultraGrid1.DataSource = dt;
ultraGrid1.DataBind();

//keep DB query
clsQB = clsQBuilder;

sFormType = sFrmType;

dbConnection = DBConn.cn;
}

private void ultraGrid1_DoubleClick_1(object sender, System.EventArgs
e)
{

******* What goes here?????

//Currently it does this:
//get primary keys to find desired record & send to
form
string[] sArrayPK = clsQB.GetPrimaryKey(sFormType);
int iLen = sArrayPK.GetUpperBound(0) + 1;
sArrPK = new string[iLen,3];

//loop through primary keys array and build array w/
primary keys & their values
for(int i=0;i < iLen;i++)
{
//Column Name
sArrPK[i,0] = sArrayPK[i];
//Column Value
sArrPK[i,1] =
Convert.ToString(dtResults.Rows[ultraGrid1.ActiveRow.Index]
[sArrayPK[i]]);
//Column Data Type
sArrPK[i,2] = dtResults.Columns[sArrayPK[i]].DataType.ToString();
}

//load form
OpenForm();
this.Close();
}

//So open form calls a new instance of the original Waypts form
through a few different functions the end result is this code:

frmWaypts newFrmWayPts = new frmWaypts(sArrPK,dbConnection);
newFrmWayPts.MdiParent=this.ParentForm;
newFrmWayPts.Show();
((frmMDI)this.ParentForm).sKeys = sArrPK;
Ok - so i just want to STAY on the same Waypts form! Please - this
can't be that hard right???? What am I missing here??? I hope I
put all the pertinent info in here. I took this application over (new
job) and I actually use to work with the guy that wrote it. Sometimes
he does things totally backwards. But I'm hoping he didn't lock me
into something I can't get out of. Not being able to go from form to
form severely limits capability I would think? I appreciate all
responses! I'm going gray!

Jen

May 22 '07 #6
On Tue, 22 May 2007 07:35:33 -0700, <ho*********@gmail.comwrote:
[...] All I want is when the grid_doubleClick
occurs on QueryResults, to populate the data on frmWaypts. Why is
that so hard? In a C# web application that would be no biggie.
It's not in a Windows application either. It's not that hard, and I can't
answer the question as to why you are finding it hard. Perhaps we should
not have offered so much variety in the answers. For my own part, I can
say that my answer was partly driven by your mention of events. Using an
event is indeed the "accepted" way to deal with this sort of thing, but by
no means required. So if that part of my reply is confusing you, just
ignore it, at least for now.
I tried the ShowDialog like someone suggested, but then I have top-level
form parent issues!
What does that mean? "top-level form parent issues!" doesn't really
describe your problem. It's not possible for anyone to help you if you
use vague descriptions of your problems.
Again, I never worked with MDI parent-child stuff
before either! So that makes no sense to me either.
Well, I haven't done MDI since the olden days (Windows 3.x). But way back
then, it was a way to have new windows contained within another window.
Assuming it still works that way, then I don't see how that's relevant to
your question. Sure, you could use MDI, but it doesn't have anything to
do with populating the original form based on a double-click on the
results form. MDI would have more to do with the *appearance* of the
forms than their functionality. You shouldn't be using MDI just to create
a parent/child reference, if the resulting appearance isn't what you
want. There are different, more appropriate ways to do that.

So, all that said, let's see if we can come up with *something* that helps
you. :)

I'm going to post excerpts from you code, changed to do what you want to
do, in the simplest way I can think of. That means not using events.
Even though events are a "cleaner" way to do this, they aren't required
and based on your current design the simplest mechanism is to simply
reference the original form. So here you go:

First, change your query form and constructor to take a reference to the
original form:

private frmWaypts _form; // new field added to frmQueryResults
class

public frmQueryResults(DataTable dt, string sFrmType,
clsQueryBuilder clsQBuilder, clsDBConn DBConn, frmWaypts form)
{
InitializeComponent();

//keep query results table
dtResults = dt;

//bind table to grid
ultraGrid1.DataSource = dt;
ultraGrid1.DataBind();

//keep DB query
clsQB = clsQBuilder;

sFormType = sFrmType;

dbConnection = DBConn.cn;

_form = form;
}

Then instead of this code:

frmWaypts newFrmWayPts = new frmWaypts(sArrPK,dbConnection);
newFrmWayPts.MdiParent=this.ParentForm;
newFrmWayPts.Show();
((frmMDI)this.ParentForm).sKeys = sArrPK;

Do this:

_form.sKeys = sArrPK;

This assumes that the above assignment is the only thing you need to
actually populate the data in the parent form.

This is by no means the only way to do this. If you wanted to take a step
further, you could instead of storing the parent form's reference
explicitly, take advantage of the fact that dialog boxes have a parent
already (passed in to the ShowDialog(IWin32Window) method, or determined
implicitly in the parameterless version of ShowDialog()). Then instead of
storing a reference to a frmWaypts in the _form field, don't bother with
the field and get your reference from the Owner property of your
frmQueryResults form (casting it to frmWaypts):

((frmWaypts)Owner).sKeys = sArrPK;

And of course, you can take it even a step beyond that by using events.
But that's not strictly necessary in this case, and might be more trouble
to you than it's worth, at least in the short run.

Pete
May 22 '07 #7
Ok - I think I figured it out. I need to do some major clean up. But
I can get it to work. I used the ShowDialog and managed to mess with
some keys that are stored to get the original form to load again with
the new data. :) Thanks for all your help! I'd still like to
understand the events better though. So I will work on that.

May 22 '07 #8
On May 22, 7:35 am, hoofbeat...@gmail.com wrote:
Wow. I am totally confused. I appreciate all the replies, but I
still can't figure this out. Maybe if I put in part of my code that
will help? I understand the whole WithEvent in VB, even though I have
never programmed in VB! All I want is when the grid_doubleClick
occurs on QueryResults, to populate the data on frmWaypts. Why is
that so hard? In a C# web application that would be no biggie. I
tried the ShowDialog like someone suggested, but then I have top-level
form parent issues! Again, I never worked with MDI parent-child stuff
before either! So that makes no sense to me either.

My Waypts form looks like this:

public class frmWaypts : System.Windows.Forms.Form
{
public frmWaypts()
{
InitializeComponent();
}

public frmWaypts(string[,] sPKeys, SqlConnection dbCn)
{
//Constructor when Modifying a Runway
//keep primary keys & values
InitializeComponent();
sArrWptKeys = sPKeys;
Wpt = new clsWaypoints(dbCn,sArrWptKeys);
dbConn = dbCn;
}

private void btnQuery_Click(object sender, EventArgs e)
{
//just putting the important pieces here. . .
frmQueryResults newFrmQueryResults = new
frmQueryResults(dtResults, clsDBQC.tWayPt, clsQB, dbConnect);
newFrmQueryResults.MdiParent = this.ParentForm;

//some if. . .else stuff going on
else
{
newFrmQueryResults.Show();
}
}

}

Now the results screen is this:

public class frmQueryResults : System.Windows.Forms.Form
{

public frmQueryResults(DataTable dt, string sFrmType,
clsQueryBuilder clsQBuilder, clsDBConn DBConn)
{
InitializeComponent();

//keep query results table
dtResults = dt;

//bind table to grid
ultraGrid1.DataSource = dt;
ultraGrid1.DataBind();

//keep DB query
clsQB = clsQBuilder;

sFormType = sFrmType;

dbConnection = DBConn.cn;
}

private void ultraGrid1_DoubleClick_1(object sender, System.EventArgs
e)
{

******* What goes here?????

//Currently it does this:
//get primary keys to find desired record & send to
form
string[] sArrayPK = clsQB.GetPrimaryKey(sFormType);
int iLen = sArrayPK.GetUpperBound(0) + 1;
sArrPK = new string[iLen,3];

//loop through primary keys array and build array w/
primary keys & their values
for(int i=0;i < iLen;i++)
{
//Column Name
sArrPK[i,0] = sArrayPK[i];
//Column Value
sArrPK[i,1] =
Convert.ToString(dtResults.Rows[ultraGrid1.ActiveRow.Index]
[sArrayPK[i]]);
//Column Data Type
sArrPK[i,2] = dtResults.Columns[sArrayPK[i]].DataType.ToString();
}

//load form
OpenForm();
this.Close();

}

//So open form calls a new instance of the original Waypts form
through a few different functions the end result is this code:

frmWaypts newFrmWayPts = new frmWaypts(sArrPK,dbConnection);
newFrmWayPts.MdiParent=this.ParentForm;
newFrmWayPts.Show();
((frmMDI)this.ParentForm).sKeys = sArrPK;

Ok - so i just want to STAY on the same Waypts form! Please - this
can't be that hard right???? What am I missing here??? I hope I
put all the pertinent info in here. I took this application over (new
job) and I actually use to work with the guy that wrote it. Sometimes
he does things totally backwards. But I'm hoping he didn't lock me
into something I can't get out of. Not being able to go from form to
form severely limits capability I would think? I appreciate all
responses! I'm going gray!
You're right: this won't be very difficult. Here's the solution:

1. Your frmQueryResults should have a public event that it raises
whenever someone double-clicks on an item to be displayed in the
frmWaypts form.
2. frmQueryResults should also expose a public property or method that
returns the item the frmWaypts needs to display.
3. When frmWaypts brings up the frmQueryResults, it should subscribe
to the event:

private void btnQuery_Click(object sender, EventArgs e)
{
//just putting the important pieces here. . .
frmQueryResults newFrmQueryResults = new
frmQueryResults(dtResults, clsDBQC.tWayPt, clsQB, dbConnect);
newFrmQueryResults.MdiParent = this.ParentForm;

//some if. . .else stuff going on
else
{
newFrmQueryResults.ItemSelected += new
System.EventHandler(newFrmQueryResults_ItemSelecte d);
newFrmQueryResults.Show();
}
}

Then, in frmWaypts:

private void newFrmQueryResults_ItemSelected(object sender,
System.EventArgs e)
{
frmQueryResults qr = (frmQueryResults)sender;
... read the property / call the method in qr to get what is to be
displayed ...
... display the information ...
}

May 22 '07 #9

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

8
by: Ron Holmes | last post by:
I want to place a background image on a windows form. Is there a way to prevent the image from Tiling without using an image box resized to the size of the form? I am using Visual Studio 2003...
0
by: MaxMax | last post by:
Can I ask the reasoning of the Event Handling of Windows Forms? Many years ago MS programmers told us that the MFC model was better than the OWL (OWL = Borland) model, because the OWL model had to...
7
by: MounilK | last post by:
Hi all, I am not sure if this is the right NG to post this question. If that's the case please point me to the correct NG. I have a class library(myLib.dll) which has a class(myClass) which has...
4
by: Sandy MacDonald | last post by:
Hi everyone, This is a very simple question, but I am new to VB.net and can't seem to get a simple call to another form to work. example: If (scenerio is true) then load frmLogin end if ...
6
by: PradeepKel | last post by:
Hi, I have 3 forms in my application. Form1 which is a MDI form calling Form2 & Form3. Form2 has a textbox "TextBox1" and Form3 has a CommandButton "Button1". I will show both Form1 & Form2 as...
2
by: Chris Dunaway | last post by:
I am attempting to use the AppDomain.UnhandledException event in a Windows Forms app and also in a Windows Service. But the event doesn't seem to be called. In a Windows Forms app, the event IS...
3
by: Neal | last post by:
managed C++ VS 2003 I have a beginner question about windows forms.... I need to call a function when a certain limit has been reached, now with the way VS sets up the .NET windows Form I get...
5
by: Paul | last post by:
Is it possible to display a form inside another form? What component should I use?
0
by: culubalo | last post by:
Ok so this has been annoying me since yesterday but should be simple enough to do. If I create, say a picture box in an array, in code in Form1.h as follows: System::Windows::Forms::PictureBox^...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.