MDI Child Controls suspend events - c#

I have a MDI Form with 2 mdi children forms. On both the children forms I have a shared usercontrol (data grid) and the way the usercontrol has to work is exactly the same except for a filter on the one form.
All works well, however, I do have a problem with Events. I created a couple of eventhandlers to detect when things like save/search/load etc happens on the data. However, I don't want both child forms to for example to fire the search event. If I search data on ChildForm1, I dont want ChildForm2 to fire the search event as well.
I tried using Visible and IsAccessible to detect if the usercontrol is on the front of the Mdi forms, but that does not work.
Another option is to see if the parent is the active Mdi form, however, I sometimes have a couple of panels as the parent etc. Which makes it a difficult solution for future development or other scenarios.
Any suggestions?
edit: what I am currently doing is:
private void TransactionLoad_Event(object sender, EventArgs e)
{
if (loading) return;
Form parentForm = this.FindForm();
Form mdiParentForm = (Form)this.TopLevelControl;
if (mdiParentForm != null && parentForm != null && mdiParentForm.ActiveMdiChild == parentForm)
LoadTransactions();
}
Thanks Eugene.

Related

Implementing the Right GUI Behavior for Form_Find

I have a simple application that consists of 2 Forms:
Form_Main, and Form_Find.
Form_Main is a big form that has a Grid on it,
Form_Find is a small form that has a TextBox and 2 buttons("Previous", "Next") on it.
Form_Find is only shown after the user presses Ctrl-F.
So far everything works good, and I am only left with one problem,
a problem that relates to the GUI.
The problem is this:
Form_Find's .TopMost property is set to True.
It works very well when I am in the application,
but when I leave the appication open and switch to another application(e.g. a browser), Form_Main is covered by the new window(e.g. the browser) like it should,
but Form_Find is still floating and shown, covering a part of the other application's window, and disturbing.
I wanted Form_Find to somehow be a child of Form_Main,
so that If I leave/minimize Form_Main, then Form_Find will not continue to appear..
and will only re-appear once I am back to the application - to Form_Main.
To do this, I set Form_Find's .Parent property to the instance of Form_Main,
and to make it work, I also needed to write a line before it, which sets Form_Find's .TopLevel property to false.
(or else I could not set a Parent to Form_Find)
This actually worked,
and now Form_Find behaves like a child form of Form_Main:
When I switch from my application to another application, both Form_Main and Form_Find are covered by the new appplication's window.
So this problem was indeed solved,
however a new problem has raised due to it, and this new problem is what I am stuck with now.
The new problem is:
Whenever I click the "Next" button in Form_Find,
it causes the Grid control on Form_Main to lose focus.
And when the Grid on Form_Main loses focus, the Grid takes the cell that was in EditMode, out of EditMode.
And this is my problem.
This did not happen before I set Form_Main to be the Parent of Form_Find.
The reason it did not happen, was because when Form_Find is not a child of Form_Main,
then when Form_Find gets focussed, the focussed control in Form_Main never knows about it..
Form_Main may lose the focus to another form, but the control inside Form_Main will never know it and will never fire any relevant event about it(only the form will).
So you see,
to make the behavior of Form_Find be well,
I need both of these things:
1) To have Form_Find somehow a child of Form_Main, so when I switch to another window, Form_Find will not continue floating on the screen, covering other applications
2) To have Form_Find not steal focus from the focussed control on Form_Main, when I click the "Next" button on Form_Find. I did have this as long as Form_Find was not a child of Form_Main, but I lost this once I succeeded in making Form_Find be a child of Form_Main.
So my question to you:
What would be the solution to this problem?
Thank you very much
To establish the corrent parent/child behavior requested you need to pass the owner form to the child one when you open the child.
This proof of concept could be tested using LinqPad
(*I am not involved in any way with them, IMHO it is just the most useful tool that you need)
Form f1;
void Main()
{
f1 = new Form();
TextBox t1 = new TextBox();
t1.Location = new Point(0,0);
TextBox t2 = new TextBox();
t2.Location = new Point(0,30);
f1.Controls.AddRange(new Control[] {t1,t2});
f1.Deactivate += onDeactive;
f1.Show();
Form f2 = new Form();
Button b = new Button();
b.Click += bClick;
f2.Controls.Add(b);
// This line pass the F1 form
// as owner of F2 establishing the
// correct parent/child behavior
f2.Show(f1);
}
void bClick(object sender, EventArgs e)
{
Console.WriteLine("Clicked");
f1.ActiveControl.Text = DateTime.Now.ToString("hh:mm:ss");
}
void onDeactive(object sender, EventArgs e)
{
Console.WriteLine("Main Deactivated");
}

How to focus a control in a form which is added on a panel of its parent form by tabbing index

I'm working on winforms in c#. I have a form which loads other forms in its panel. Now my child forms have many textboxes.
I want to set focus on one of those textboxes by loading my children forms by setting tab index to zero.
But it isn't happening when i load my children forms. I have taken care of the tab stop properties & i also went through the tabbing order of the forms. But the problem is still there.
When i load children forms from startup it focuses zero indexed control. I guess my problem is that i am loading these forms in a panel of a parent form. Any solution to this problem?
The Windows Forms controls in the following list are not selectable. Controls derived from these controls are also not selectable.
Panel
GroupBox
PictureBox
ProgressBar
Splitter
Label
LinkLabel (when there is no link present in the control)
Focus is a low-level method intended primarily for custom control authors. Instead, application programmers should use the Select method or the ActiveControl property for child controls, or the Activate method for forms.
https://msdn.microsoft.com/en-us/library/system.windows.forms.control.focus.aspx
You can set focus to a control in a form which is added on a panel of its parent form by creating an instance of child form in the parent form and then setting focus to child form controls.
Make an instance of child form:
ChildForm formInstanceName = new ChildForm();
And then you can set the focus property for particular control as:
formInstanceName .controlname.Focus();
And before doing this make sure you add the child form to the respective panel.
Here is the snippet of the code I used:
Form1 childform1 = new Form1();//creating an instance of child form
private void btn_Click(object sender, EventArgs e)
{
Panel2.Controls.Clear();//To clear existing controls on panel
Panel2.Controls.Add(childform1); // To add child form controls on the panel.
childform1 .textbox1.Focus(); //To set focus to control of child form
}
I hope this helps you..

C# Parent form not updating from child

I have two Forms
Parent Form : properties : Total Value. Button to load child form.
Child Form: property : insert Value.
When I run application, Parent form loaded first. I can load second (Child) form by click button.
Problem is that when I insert value in child form parent form is not showing any changes even I pass value by delegate and other methods.
I don't want to reload Parent Window. Please help
What you should be doing is creating events on the child for (or using the existing events if they will do the job) and having the parent form subscribe to those events.
One common example is to have the parent hide itself, show the child, and then show itself again when the child is closed. Here is some code that does that:
//in parent form
private void someButtonClickHander(object sender, EventArgs args)
{
ChildForm child = new ChildForm();
this.Hide();
child.Closing += (sender2, args2) =>
{
var someResultFromChildForm = child.SomePropertyOnChildForm;
this.Show();
}
child.Show();
}
If the closing event doesn't work for you (maybe you want to do something when the child form presses a button) you may need to have the child create it's own event. There are lots of tutorials on MSDN or other sites on how to do this. If you have trouble with that (or any other aspect of this design) please ask for clarifications in comments.
If you want to keep data consistent between multiple forms, I recommend putting the data into an object that you can reach from both forms.
The most direct way is to implement INotifyPropertyChanged for the object, so you can bind to this object in both forms and any changes made will trigger the property change event.
For more complex scenarios I make an object that has custom events that I can subscribe to, as INotifyPropertyChanged can be lack the subtlety needed in complex scenarios. As an example, I have a "Helm" object for my primary navigation form that all of the UI elements subscribe to. If a navigation event occurs, the helm does all of the navigation and data loading, and then it triggers a series of events that the UI listens to.
For a simple parent child this can seem like overkill, but this model (having one truth for the current state that the UI simply subscribes to) allows your UI to evolve and for each element of the UI to only worry about its own needs.
Have a Property called Parent in your child form. When you create the instance of the Child,Pass the current object( parent form object) to the constructor where you will set it as the Parent property value of child. In Parent form Have a Public Method in your Parent form. P
parent form
Form1 : Form
{
decimal _totalPrice;
public void UpdateTotal(decimal val)
{
_totalPrice=_totalPrice+val;
lblTotal.Text=_totalPrice.ToString();
}
}
Child Form
Form2:Form
{
public Form1 Parent { set;get;}
public Form2(Parent parent)
{
this.Parent =parent;
}
}
When creating the object of Child form
Form2 objChjild=new Child(this);
//do whatever
Now from child form, if you want to update the total,
call like this
this.Parent.UpdateTotal(200);

Closing One Form From Another Form?

I have a little application that creates alerts whenever a change to a database is made.
I have a few options in the alert form that pops up.
One of the options opens another form (a child form) asking the user for further information.
When the child form gets the necessary information from the user, I want it to close as well as the parent form. So far, I only know how to close the child form, but not the parent form.
Parent form > Opens child form
Child gathers information > User clicks ok in child > child closes, parent closes
^this is what I want
I just don't have the brain power to think about how to communicate across forms to accomplish closing the parent form.
Any help would be much appreciated. Actually, it would be super appreciated. If I could learn how to make my forms communicate with each other, I could really do a lot of damage (in a good way 8D ).
In the parent form, you can do something like this:
ChildForm f = new ChildForm();
f.FormClosed += (o,e) => this.Close();
f.Show();
Try this in the parent form:
using (var childForm = new ChildForm())
{
if (childForm.ShowDialog() == DialogResult.OK)
{
Close();
}
}
Your child form should return a DialogResult by clicking buttons (OK or Cancel) and/or setting the AcceptButton and CancelButton properties in the designer.

Removing the default MDI menu of a MDI Container form when a MDI Child is maximized

I am working on a .NET C# application that has a main Form which is MDI container. When the user maximizes a MDI child, Windows draws a control strip right under the title bar of the container Form which has the Icon of the child and the system buttons on the right. Basically, what I need is hide this strip and use a custom control to provide the same functionality.
Is there any way to prevent Windows from drawing this MDI strip?
Actually, I found an easy and interesting way to remove this thing from my form by assigning the MainMenuStrip property of the Form with a dummy MenuStrip control (without putting it in the Controls collection of the Form):
private void OnForm_Load(object sender, EventArgs e)
{
this.MainMenuStrip = new MenuStrip();
}
This prevents the default MDI caption from being painted since the Form delegates its functionality to its default menu strip if any. Since the MenuStrip control is not in the Controls collection of the Form, it is also not visible and thus it just serves as a dummy menu used for hiding the nasty MDI menu when a child is maximized.
This conversation from years ago suggests that there's no way to do it, and he ended up with User Controls on the main form, instead of actually using an MDI interface:
http://answers.google.com/answers/threadview/id/135136.html
Every other thread I can find online is either abandoned with no answers or a dead-end. I can't believe this functionality if so cumbersome and not something natively available.
There is an easier way than adding the code to the Load event for every form. Just place this code in the MdiParent form and substitute MenuStrip for the actual name you're using for your menustrip control.
Private Sub MenuStrip_ItemAdded(ByVal sender As System.Object, ByVal e As System.Windows.Forms.ToolStripItemEventArgs) Handles MenuStrip.ItemAdded
Dim s As New String(e.Item.GetType().ToString())
If s = "System.Windows.Forms.MdiControlStrip+SystemMenuItem" Then
e.Item.Visible = False
End If
End Sub

Categories