Limiting number of instances of windows in an MDI application - c#

I want to restrict the user to create multiple instances of a form in an MDI application.
If one instance of that form is opened it must get focus. If it is not a new instance it must be created.
How can I do this?

You can do it like this.
Create a static Method:
public static Form IsFormAlreadyOpen(Type FormType)
{
foreach (Form OpenForm in System.Windows.Forms.Application.OpenForms)
{
if (OpenForm.GetType() == FormType)
return OpenForm;
}
return null;
}
And then when you create your child form.
frmMyChildForm frmChild1;
if ((frmChild1 = (frmMyChildForm)IsFormAlreadyOpen(typeof(frmMyChildForm))) == null)
{ //Form isn't open so create one
frmChild1= new frmMyChildForm ();
}
else
{ // Form is already open so bring it to the front
frmChild1.BringToFront();
}

You could use a singleton-pattern-approach, and let the form have an Instance-member-variable that keeps track of whether it's been initialized or not.
http://en.wikipedia.org/wiki/Singleton_pattern

Maybe something like this could help you
Form frmToCreate;
String strClassName=typeof(FormToCreate).Name
frmToCreate = GetForm(strClass);
if(frmToCreate == null)
{
//create the form here
}
frmToCreate.MdiParent = this; //supposing you are inside of the mainwindow (MDI window)
frmToCreate.Visible = true;
//other code goes here
where GetForm would be something like this
public Form GetForm(String type)
{
int i;
Form[] children = this.MdiChildren; //or mdiwindow.MdiChildren
for (i = 0; i < children.Length; i++)
{
if (children[i].GetType().Name == type)
{
return children[i];
}
}
return null;
}
If just a matter of playing with MdiChildren property.

Related

How to affect child form from parent form in mdi c#

My problem is that I have created child's object and show child first time. but when second time I just want to change value of child's label from parent but don't want to show another form.
Here is my code.
First time
ChildForm ObjChild = new ChildForm("Hi");
ObjChild.Show();
On second time I just want to set Bye in place of Hi.
ChildForm ObjChild = new ChildForm("H!");
ObjChild.BringToFront();
Because child form is already opened.
This is my child Form
public Form1(string p_Param)
{
InitializeComponent();
Label1.Text = p_Param;
}
Constructors call one time when object created. You must implement a new public void or function rather than a constructor to do that.
public void ChangeLabelText(string txt)
{
Label1.Text=txt;
}
EDIT:
In your parent form;
Out of functions;
chilFrm ChildForm;
Inside any function;
if (chilFrm == null)
{
chilFrm = new ChildForm();
chilFrm.TopLevel = false;
chilFrm.Parent = this;
chilFrm.StartUpProsecc("Created New");
chilFrm.Show();
}
else
{
chilFrm.StartUpProsecc("Showed the existing.");
chilFrm.BringToFront();
}

open new winform

i have treeview which each node tag contain form name , when i click on node i open the form
my code is as follows
private void treeView1_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
{
NodeClick(Convert.ToString(e.Node.Tag));
}
public void NodeClick(string formName)
{
switch (formName)
{
case "frmPartMaster":
frmPartMaster partMaster = null;
if ((partMaster =
(frmPartMaster)Globale.IsFormAlreadyOpen(typeof(frmPartMaster)))
== null)
{
partMaster = new frmPartMaster();
partMaster.Show(this);
}
else
{
partMaster.Activate();
partMaster.WindowState = FormWindowState.Normal;
partMaster.BringToFront();
}
break;
}
}
this code is working fine but i have 1000's of form , for each for form i have to right case the code.
is it possible if i passed the form it open it open like in single case?
You can create instance of a form class by the call of Activator.CreateInstance
public void OpenOrActivateForm(string formType)
{
var formType = Type.GetType(formType);
var form = Globale.IsFormAlreadyOpen(formType);
if(form == null)
{
form = Activator.CreateInstance(formType);
from.Show(this);
}
else
{
form.Activate();
form.WindowState = FormWindowState.Normal;
form.BringToFront();
}
}
Why don't you just put a reference to a form in the Node's Tag and then use that directly
private void treeView1_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
{
NodeClick(e.Node.Tag as Form);
}
public void NodeClick(Form theForm)
{
if(theForm == null) return;
if(theForm.Visible == false)
{
theForm .Show(this);
}
theForm .Activate();
theForm .WindowState = FormWindowState.Normal;
theForm .BringToFront();
}
You should be able to add the form to the node, the node should have a field, tag i think it is that is of type object. Add your form there then extract it from the tag. That way you will not have to use a case statement but 1 single statement that works for all forms.
Instead of using switch case for every form, you can use Activator.CreateInstance method.
Refer this MSDN Article.
You can store Fully Qualified Name in the tag and use it to instantiate appropriate form.
You could use this approach:
Define a Dictionary of strings and actions like this
Dictionary<string, Action> dic = new Dictionary<string,Action>();
dic.Add("frmPartMaster", OpenPartMaster);
.....
add the appropriate action
private void OpenPartMaster()
{
frmPartMaster partMaster = null;
if ((partMaster =
(frmPartMaster)Globale.IsFormAlreadyOpen(typeof(frmPartMaster)))
== null)
{
partMaster = new frmPartMaster();
partMaster.Show(this);
}
else
{
partMaster.Activate();
partMaster.WindowState = FormWindowState.Normal;
partMaster.BringToFront();
}
}
and when you need to call that form instead of an infinite switch use
dic[formName].Invoke();
in this way you have a centralized point where you add the specific action to execute when a particular form is requested and you keep all the functionality already written.
Of course you need to refactor the switch cases in separate methods.
This approach is interesting if you have different actions (cases) for your form and not a always the same sequence of repeating code.

How to perform action for specific forms in the class of the BaseForm?

I want to let my program know which form is opened and then do some specific action for that form. Forms are opened in a main-window with an overview and the user can click on an image to open a new form. This main-window is not my BaseForm for the forms I want to open.
To check what form is open, I tried the following code:
bool thisOne;
bool theOtherOne;
private void FormCheck()
{
foreach (Form form in Application.OpenForms)
{
if (form is frmRectangle)
{
thisOne = true;
theOtherOne = false;
break;
}
if (form is frmCircular)
{
theOtherOne = true;
thisOne = false;
break;
}
}
}
I set the form-relatedbooleans to true, so I can use them in another function, something like this:
private void ActionTime()
{
if (thisOne)
Debug.WriteLine("ThisOne is open");
//Do some stuff for the ThisOne form
if (theOtherOne)
Debug.WriteLine("TheOtherOne is open");
//Do some stuff for TheOtherOne form
}
ActionTime is called by a ClickEvent, but the action never happens... I guess something's going wrong it the foreach-loop.

Configure buttons on one form from another form

I have an application that has a main form which has 10 buttons that are user configurable.
I have another form with which to configure those 10 buttons actions.
What is the best way for me to configure these 10 buttons?
Currently, I'm passing the 10 buttons as a List to the second form, and link them to the appropriate combobox tag.
The problem is if sometime in the future I decide to add a button or rearrange them, I'll have to rewrite the code. Anyone know a better way?
private readonly List<PictureBox> pictureBoxes;
private readonly List<ComboBox> comboBoxes;
public Shortcut_Buttons (List<string> stringsList, List<Button> sButtons)
{
InitializeComponent();
pictureBoxes = Controls.OfType<PictureBox>().ToList();
comboBoxes = Controls.OfType<ComboBox>().ToList();
if (pictureBoxes.Count != sButtons.Count)
throw new ArgumentException("Not enough Buttons/Pictureboxes.");
int i = 0;
foreach (var pictureBox in pictureBoxes)
{
pictureBox.BackgroundImage = sButtons[i++].BackgroundImage;
}
i = 0;
foreach (var comboBox in comboBoxes)
{
comboBox.DataSource = stringsList;
comboBox.Tag = sButtons[i++];
comboBox.SelectedIndexChanged += SetShortcutButton;
}
}
Accessing directly the form by getting instance?
Like:
private static MainForm _this = null;
public static MainForm Instance { get { return _this; } }
public MainForm()
{
_this = this;
...
}
Meanwhile in another place:
MainForm.Instace.somePublicComponents....

Lazy load forms

I have a .NET CF program (running on a Smartphone) and I have written an options page for it.
On the options page I have links to 6 other forms which contain the actual options.
When the main form loads it creates the 6 subforms and stores them in a list ready to be launched. The issue with this is the initial creation time required to make these forms, which makes the main settings form slow.
What I would ideally like, is a way to just specify the type and parameters required to create the subform on load, then actually create the form when needed.
Here is code snippets of how it currently works:
Form_OnLoad():
AddSettingsOptions("General", new General());
AddSettingsOptions("Action Alert", new BaseAlertForm("Action Alert Settings", SystemManager.ActionAlert));
AddSettingsOptions("Comms Alert", new BaseAlertForm("Comms Alert Settings", SystemManager.CommsErrorAlert));
AddSettingsOptions("Advanced", new Advanced());
AddSettingsOptions("Diagnostics", new Diagnostics(_unitWatcher));
AddSettingsOptions("About", new About());
The form is stored in the Tag section of a list (which displays the sub options)
private void AddSettingsOptions(String name, Form form)
{
listViewSettings.Items.Add(
new ListViewItem(
String.Format(" {0} {1}", listViewSettings.Items.Count + 1, name))
{
Tag = form
}
);
}
If an option is pressed the following function is called to launch the form
private void ShowSubSetting(ListViewItem item)
{
if (item == null)
return;
object tag = item.Tag;
Form form = tag as Form;
if (form != null)
{
form.ShowDialog();
//form.Dispose();
}
}
I'm sure there is a pretty easy way to do this, I'm just struggling with the correct way.
Thanks
You can do it this way:
AddSettingsOptions("General", ()=> new General() );
AddSettingsOptions("Action Alert", ()=> new BaseAlertForm("Action Alert Settings", SystemManager.ActionAlert) );
// etc ...
void ShowSubSettings(ListViewItem item ){
if ( null == item ) { continue; }
object tag = item.Tag;
Func<Form> func = tag as Func<Form>;
if ( null != func ) {
Form frm = func();
if ( null != frm ) {
frm.ShowDialog();
}
}
}
If you are using C# 2.0, you must use
delegate { return new General(); }
instead of
()=> new General();

Categories