Show MdiChild on top of all other MdiChildren - c#

Does anyone know about Multiple Document Interfaces in C#? I'm having trouble with Form.Show(this) to keep one of the child forms perpetually on top of the rest. If the form already has an owner (set to MdiParent), then the program throws an exception when calling the show method.
Here's a switch case that's supposed to create and display a child form, but errors out due to the problem stated above. Are there any alternatives to this to keep the form on top of all the others?
case Page.Call:
if (call == null)
{
call = new CallForm();
call.MdiParent = this;
call.Dock = DockStyle.Fill;
}
call.Show(this);
break;

Related

Ensure new Form is on top of the stack

In WinForms I need to ensure that newly opened Form is on top of the stack and does not hide behind Form that instantiated it. I do not want to use TopMost property as it forces new form to stay on top of all Forms opened by all running processes. I just need to have my new Form to open on top of all forms in current application.
This method will check the current application OpenForms collection for a window with a title you pass in. It will activate the window if it is found, or have the window manager launch one.
Not sure how you plan on Z-Ordering your windows, but you could use the loop in the code and do something with each openform.
public void FindWindowOrMake(string theTitle)
{
var found = false;
foreach (var openForm in Application.OpenForms.Cast<Form>()
.Where(openForm => openForm.Text.Equals(theTitle)))
{
found = true;
openForm.Activate();
break;
}
if (found) return; // target found and activated
// create new instance
WinMgr.Create(theTitle);
}

C# MDI Form in Panel

I want to make a panel contain a MDI form. I want to put MainWin into a Panel (progPanel) that is in another form of DesktopApp. I have used this C# Panel As MDI Container
I cannot recode the MainWin without MDI because that would take forever and I would lose some functionality.
Canvas.MainWin canvasForm = new Canvas.MainWin();
MdiClientPanel mdiClientPan = new MdiClientPanel();
canvasForm.MdiParent = mdiClientPan.MdiForm;
progPanel.Controls.Add(mdiClientPan);
public class MdiClientPanel : Panel
{
private Form mdiForm;
private MdiClient ctlClient = new MdiClient();
public MdiClientPanel()
{
base.Controls.Add(this.ctlClient);
}
public Form MdiForm
{
get
{
if (this.mdiForm == null)
{
this.mdiForm = new Form();
//set the hidden ctlClient field which is used to determine if the form is an MDI form
System.Reflection.FieldInfo field = typeof(Form).GetField("ctlClient", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
field.SetValue(this.mdiForm, this.ctlClient);
}
return this.mdiForm;
}
}
}
I get the error Form cannot be both an MDI child and MDI parent on line canvasForm.MdiParent = mdiClientPan.MdiForm;. I have tried using DesktopApp.ActiveForm.MdiParent and changing Form in MdiClientPanel to Canvas.MainWin, but nothing is working. Any suggestions?
You cannot do this.
The error message should have been clear enough. So should have been the answer to the other question that you linked.
MDI has been considered obsolete for many years now. Users find it excessively confusing, and there are much better paradigms for unifying multiple windows within a single container. Consider, for example, a tab control. Users are already familiar with this, since every browser in existence uses tabs to display multiple web pages.
Yes, rewriting the application to avoid MDI will take time. But it is your only option, because your idea won't work. And there's an additional benefit to the user.
To be honest, I'm not really sure why you would want an MDI form inside of a panel in the first place. Consider a floating toolbox window as an alternative.

Programmatically changing form controls

I'm not sure if this can be done but I'd like to know if it is possible to completely alter what controls are on the form programmatically, similar to what happens with installers; when you click the next button the form doesn't hide or close and open the next form, it mearly loads a different set of controls(at least, that's how it appears).
Is it possible to do this with C# in Visual Studio? Or do you have to use tabs or hidden panels?
I think what you're looking for is UserControl. A UserControl is like a form in the way you can use it as a container for other controls.
You can find a walkthrough here.
In the case of installers you mentioned or wizards in general you can design a different UserControl for each step and load each of them in a reserved area in the form. The reserved area can be a panel.
for example assume you have a button which calls a method with wizards step number as parameter:
UserControl _step1Control = new UcStep1Control;
UserControl _step2Control = new UcStep2Control;
private void SetStep(int stepNumber)
{
panel1.Controls.Clear();
switch(stepNumber)
{
case 1:
panel.Controls.Add(_step1Control);
break;
case 2:
panel1.Controls.Add(_step2Control);
break;
default:
break;
}
}
Yes you can do anything to the controls programatically. The designer that you use also generates C# code in the background.
In order to add a new control to your form, you use the the Form.Controls.Add(Control c) method. Any class which inherits from Control (Button, ListBox, etc) can be used. To remove it, you use the Remove method instead of Add.

Statically located winforms in C#

I have three forms in C#, now when I want to show form2 I hide the main one and show the form and then when done working, hide the second form and show the main form again - I am doing this with the simple hide and show functions in winforms. Now the problem is every called form is placed on a different location on the screen, while I want all of them to stay on the same place. How to do it?
Try setting the owner of the form when you call .Show()
You can also set the start position before you call show with .StartPosition = FormStartPosition.CenterParent
Or set the form.Location property after you call show
See here and here for more details
You no doubt have a bug in your code, you are creating a new instance of the form instead of calling Show() again on the hidden form object. That's a bad kind of bug, it will make your program consume a lot of machine resources, ultimately it will crash when Windows refuses to allow your process to create more windows.
To make your scheme work, you have to write code that distinguishes between a closed form and a hidden one. Best way to do that is to explicitly keep track of its lifetime with the FormClosed event. Like this:
private Form2 form2Instance;
private void button1_Click(object sender, EventArgs e) {
if (form2Instance == null) {
// Doesn't exist yet, so create and show it
form2Instance = new Form2();
form2Instance.FormClosed += delegate { form2Instance = null; };
form2Instance.Show();
}
else {
// Already exists, unhide, restore and activate it
form2Instance.WindowState = FormWindowState.Normal;
form2Instance.Visible = true;
form2Instance.BringToFront();
}
}

Force a usercontrol on web page to reinitialize iteself

There are 2 user controls, one is inside the other.
These controls are located on an .aspx.
One control is a modal popup the other is a custom search control (the search control is inside the modal popup).
After a user has completed a search and closes the form, the next time the popup opens (for the same user) the old values are still present.
How can I clear the values out each time the form loads?
Edit:
Is it possible to capture the popup closing event?
You could clear all the values using javascript- here is an example using jquery:
http://beckelman.net/post/2008/09/24/Clear-Input-Fields-in-an-AjaxControlToolkit-ModalPopup-When-Cancel-is-Clicked.aspx
For one of the applications I currently maintain we use a recursive function to reset all the fields within the control. I have added it below but remember it is used in a C# windows application not a web application. Hope it helps.
public static void ResetFields(Control.ControlCollection pageControls)
{
foreach (Control contl in pageControls)
{
var strCntName = (contl.GetType()).Name;
switch (strCntName)
{
case "Button":
contl.Enabled = true;
break;
case "TextBox":
var txtSource = (TextBox)contl;
txtSource.Text = "";
break;
case "ListBox":
var lstSource = (ListBox)contl;
lstSource.SelectedIndex = -1;
lstSource.Enabled = true;
break;
case "ComboBox":
var cmbSource = (ComboBox)contl;
cmbSource.SelectedIndex = -1;
cmbSource.Enabled = true;
break;
case "DataGridView":
var dgvSource = (DataGridView)contl;
dgvSource.Rows.Clear();
break;
case "CheckBox":
var chkSource = (CheckBox)contl;
chkSource.Checked = false;
chkSource.Enabled = true;
break;
}
ResetFields(contl.Controls);
}
}
As it turns out there is no method on the control to clear out the values on the control.
So what I have to do is create the method on the search control to clear out the control and create a method on the popup control to capture the popup open or close event to trigger the clear method.
At first I wasn't going to be able to change the control..since explaining that this was the only way to solve the issue the control can be changed..thank god! And since the method is not going to be a default option it won't affect anywhere else the controls are used.
Assuming this user control has some client side JS code associated with it, I would modify the control to clear out its search values and results upon closing the modal popup.
This will ensure when the modal popup is reopened its in the correct state for new searches.
Sys.Application.add_init wouldn't work in this case since that will only run once when the page is loaded.
You need to write some new JS when the model popup is cancelled or closed.
Modifying the control will be your best option here so all other pages that use this control can take advantage of the new reset functionality.
It's difficult to give you any more specific information at this time without knowing the structure of your page, usercontrol and any existing javascript.

Categories