Single reusable function to open a single instance of form - c#

I am trying to create a reusable function that can open a single instance of form. Means if a form is not already open it should create and show the new form and if already open it should bring the existing form to front.
I was using the following function,
if (Application.OpenForms["FPSStorageDemo"] == null)
{
FPSStorageDemo fp = new FPSStorageDemo();
fp.Name = "FPSStorageDemo";
fp.Show();
}
else
{
((FPSStorageDemo)Application.OpenForms["FPSStorageDemo"]).BringToFront();
}
But I have to write this code again and again whereever I have to open a form. But I need a single reusable function that can do this job.
I wrote a function like,
void OpenSingleInstanceForm(Type TypeOfControlToOpen)
{
bool IsFormOpen = false;
foreach (Form fm in Application.OpenForms)
{
if (fm.GetType() == TypeOfControlToOpen)
{
IsFormOpen = true;
fm.BringToFront();
break;
}
}
if (!IsFormOpen)
{
Object obj = Activator.CreateInstance(TypeOfControlToOpen);
//obj.Show(); //Here is the problem
}
}
But at the end I don't know how to show the new form instance. Can anybody suggest how to do it? Is this wrong or there is another way to do this?
Thanks in advance.

public static class FormUtility
{
public static FormType GetInstance<FormType>() where FormType : Form, new()
{
FormType output = Application.OpenForms.OfType<FormType>().FirstOrDefault();
if(output == null)
{
output = new FormType();
}
//you could add the show/bring to front here if you wanted to, or have the more general method
//that just gives a form that you can do whatever you want with (or have one of each).
return output;
}
}
//elsewhere
FormUtility.GetInstance<Form1>.BringToFront();
I'd also like to take the time to mention that while having methods like this are quick and easy to use, in most cases they are not good design. It leads you to the practice of just accessing forms globally rather than ensuring that when forms need to communicate with each other they do so by exposing the appropriate information through the appropriate scope. It makes programs easier to maintain, understand, extend, increases reusability, etc. If you have trouble determining how best for two or more forms to communicate without resorting to public static references to your forms (which is exactly what Application.OpenForms is) then you should feel free to post that question here for us to help you solve.

You are looking for Singleton
Check this Implementing Singleton in C#

Related

WPF validation of input (on-the-fly) and unit test. Best practice for design

I want to add a new form to an existing solution. The solution already has a Validator class, so I want to expand this class.
The Form I want to create contains a Textbox (for the input) and a Button. When the input is the correct format the submit button is enabled. The input must adhere to a certain regular expression: "^[A-Za-z]{2}[0-9]{5}$". I'm checking the input (on-the-fly) in the Form class like this:
private void inputTbx_TextChanged(object sender, TextChangedEventArgs e)
{
SubmitButton.IsEnabled = Validator.IsInputValid(inputTbx.Text, RegexExpression);
}
I've put the regular expression as a variable in the Form class. I put it here because it is relevant to the textbox of this form only.
private const string RegexExpression = "^[A-Za-z]{2}[0-9]{5}$";
Here's the validation code:
public static bool IsInputValid(string inputToBeChecked, string regexExpression)
{
if (inputToBeChecked == null || regexExpression == null)
{
return false;
}
var regex = new Regex(regexExpression, RegexOptions.None);
return regex.IsMatch(inputToBeChecked);
}
So far so good. It seems to work fine. But I want to unit test it like so:
[TestCase("aZ13579")]
public void ValidateInputOkTest(string input)
{
Assert.IsTrue(Validator.IsInputValid(input, RegexExpression));
}
But to do it like this I have to have a string in my ValidatorTest class similar to the Regular-expression used in the Form class. This doesn't seem like the right way to do it. What I really want to do is get the Regex expression from the form class, so I am sure it's the correct Regex-expression that I'm using. Otherwise the Regex-expressions could easily get out of sync.
Here are the questions:
What is best practice here?
How do I get to this expression? I've tried doing it using Reflection, but I get a Threadstat error because it's a GUI component. Should I move the Regular-expression? If so where to?
I'm thinking there must be a smart way to do this. A smart design perhaps. Suggestions and comments are welcome.
You're probably going to want to back up a step and start to research the 'MVVM' design pattern. When you hear people talk about putting no code in the code behind, testing like this is one of the big benefits (among many others).
MVVM is too big a topic to handle in a simple answer like this. I'd search around on the web, and I'm sure other people have some good tutorials.
Just to be clear, it can be a big learning curve, but it's totally worth it. MVVM is what makes WPF much much (MUCH) better than WinForms, rather than merely different.
Just to address your question a little more specifically, you won't be testing a GUI object like a Window or UserControl. You'll be testing a view model which is just a regular class.
Here's a simplified version of what you might see
public class MyScreenViewModel : INotifyPropertyChanged
{
private const string RegexExpression = "^[A-Za-z]{2}[0-9]{5}$";
public bool UserInputIsValid { get { stuff; } set { stuff; }}
public string UserInput { get { stuff; } set { stuff; ValidateUserInput();} }
private void ValidateUserInput()
{
if (UserInput == null)
{
return false;
}
var regex = new Regex(RegexExpression, RegexOptions.None);
UserInputIsValid = regex.IsMatch(UserInput);
}
}
A view model in MVVM is the real logic of your screen. It will expose simple properties that the view can bind to for display/input, but the view isn't necessary for testing the logic.
Then your test looks something like:
[TestCase("aZ13579")]
public void ValidateInputOkTest()
{
var vm = new MyScreenViewModel();
vm.UserInput = "SomeValidText";
Assert.IsTrue(vm.UserInputIsValid);
}
[TestCase("aZ13580")]
public void ValidateInputNotOkTest()
{
var vm = new MyScreenViewModel();
vm.UserInput = "SomeInvalidText";
Assert.IsFalse(vm.UserInputIsValid);
}

Create a new instance of a control dynamically

Ok so I have a form I'm building that's going to change it's interface by using custom controls. What I'm trying to do is make several checks before a new control is created, like checking if one is already up. I have everything working just fine but I can't seem to create the new control dynamically, without creating it before running the checks which defeats the purpose.
The controls all implement an interface called ICustomControl and inherit from a MasterControl. Then I have a custom control called JobForm, and a button on the main form that calls the method like so: Check_Controls(newJobForm)
JobForm newJobForm;
private void Check_Controls(Control control) // Checks current controls to see if a new one can be opened
{
bool currentControl = false;
foreach (Control c in this.Controls)
{
if (c is ICustomControl && c != masterControl)
currentControl = true;
}
if (currentControl)
{
TimedMessageBox timedMessage = new TimedMessageBox("There is currently an open form. Please close the current control before opening another.");
timedMessage.ShowDialog();
}
else
{
Control c = (Control)Activator.CreateInstance(control.GetType());
this.Controls.Add(c);
Position_Control(c);
c.Show();
}
}
I dont't want to create a new instance of the custom control like: JobForm newJobForm = new JobForm(); before running the check method, I want to pass the reference to the check method and then have it create the new instance after it's checks are complete. In this way no matter how many new custom controls I wind up adding to the application, all I have to do to set one up is create the reference variable, then for the button call the check method and pass it the reference.
Anyone know how I can do this?
I think you are thinking about the problem backwards. Instead of saying "I have control X, is it valid?" think "would control X be valid, if so create". You are wanting to make checks to see if a control is valid, yet you want to send in a reference to that control.
Your code doesn't check for specific types of control, but rather just that at least one control belonging to the current form implements your interface. If this is the intended behavior, just have a function that does your initial check to see if any ICustomControl exist on your form. If that function return false, then go along with your creation.
You can accomplish this with a single function by using a constrained generic. This also gets you away from the less-than-ideal practice of using Activator and other reflection methods for dynamic type generation:
private void CheckAndAddControl<ControlType>()
where ControlType : MasterControl, new()
{
bool currentControl = false;
foreach (Control c in this.Controls)
{
if (c is ControlType)
{
currentControl = true;
break;
}
}
if (currentControl)
{
TimedMessageBox timedMessage = new TimedMessageBox("There is currently an open form. Please close the current control before opening another.");
timedMessage.ShowDialog();
}
else
{
var c = new ControlType();
this.Controls.Add(c);
Position_Control(c);
c.Show();
}
}
You would then use this function as follows:
CheckAndAddControl<JobForm>();

C# - two ways for calling this generic method. Is there any difference in?

I use this code to load a MDIchild form from within another MDIchild form. I'm learning still how to use generics in my method so when I get my method to work finally with the help of the people here I end u with two slightly different codes which in my case do the job the same way. So my question is - is it coincidence that those two variations do the same job or there's just no difference between the two approaches.
So here is version 1:
protected void LoadAForm<T>(ref T sendTo) where T : Form
{
MainForm frm = this.MdiParent as MainForm;
if (frm != null)
{
sendTo = SingletonFormProvider.GetInstance<T>(frm, true);
sendTo.MdiParent = frm;
sendTo.Dock = DockStyle.Fill;
sendTo.Show();
}
}
And here is version 2:
protected void LoadAForm<T>(ref T sendTo) where T : Form
{
MainForm frm = this.MdiParent as MainForm;
T temp;
if (frm != null)
{
temp= SingletonFormProvider.GetInstance<T>(frm, true);
temp.MdiParent = frm;
temp.Dock = DockStyle.Fill;
temp.Show();
}
}
So is there (if any difference) to use the T temp instantiation or it's just the same thing?
The main difference is that in the 2nd scenario, your newly created and shown form will not be available outside LoadAForm in your sendTo param.
The first method seems to work correctly, accomplishing what it was intended for by passing a reference parameter to it.
Another natural way is to return the newly created as a function return value form instead of returning it throug a ref'ed parameter.
LATER EDIT:
Frankly said, as Henk Holterman said, you are misusing the ref usage.
By the way, if you still want to pass a parameter to that method, use out instead of ref!
Ok, this is what I mean: declare your method like this:
protected T LoadAForm<T>() where T : Form
and return the form you just instantiated. Simple.
This has nothing to do with generics. It is about the (mis)use of ref parameters.
So is there (if any difference) to use the T temp instantiation or it's just the same thing?
Inside this method there is no difference. But after the call, the argument passed to 'sendTo' will be changed by version 1 and stay the same when using version 2.
Which one is correct cannot be guessed from this piece of code.

Are typecasts a sign of poorly designed code?

I'll be the first person to tell someone that my code design could use improvement. I can't help but feel that when I have typecasts in my code that its a sign that something needs to be redesigned to remove the typecasts. This question sort of has two parts to it, the first being simply the one posted: Are typecasts a sign of poorly designed code?
The second question is based on the first, if typecasts are as evil as I feel they are, then how could the below situation be avoided?
class InputPanel : Control
{
public event EventHandler InputEvent;
}
class OutputPanel : Control
{
}
class MainWindow : Form
{
public MainWindow()
{
var loadButton = new Button();
loadButton.Click += new EventHandler(HandleButtonClick);
var inputPanel = new InputPanel();
inputPanel.InputEvent += new EventHandler(HandleInputEvent);
bodyControl = inputPanel;
}
private void HandleButtonClick(object sender, EventArgs args)
{
OpenFileDialog dialog = new OpenFileDialog();
if (dialog.ShowDialog(this) == DialogResult.OK)
{
var data = LoadDataFromFile(dialog.FileName);
var inputPanel = bodyControl as InputPanel; // Ugly typecast...
if (inputPanel != null)
{
inputPanel.PopulateFromData(data);
}
}
}
private void HandleInputEvent(object sender, EventArgs args)
{
var outputPanel = new OutputPanel();
bodyControl = outputPanel;
}
Control BodyControl;
}
The reasoning behind the above code is that the MainWindow form contains a MenuStrip (simplified to a button in this example) and a single control (the BodyControl). As the displayed control needs to be changed from the input panel to the output panel, via the button click, you can simply reassign the BodyControl field (adjust parents and such). This means only one panel is loaded at a time, layout logic becomes simplified because there is only one panel to position within the MainWindow (two if you include the MenuStrip) as opposed to conditionally laying out multiply 'body' controls based on which state the program is in (input vs. output).
You can make your code much cleaner (and avoid the typecast) by using an interface or a common base class for the two controls (inputPanel and outputPanel). Simply store BodyControl as the base class or interface (instead of Control). Assuming the interface or base class implements the PopulateFromData method, you wouldn't need the cast at all.
Also be sure you're aware of the where clause in C#. It can come in handy when dealing with similar scenarios.
Typecasts are not a sign of poorly designed code. Lots of typecasts, however, are somewhat indicative of poorly designed code.
then how could the below situation be avoided?
You could store an InputPanel and OutputPanel variable and use a flag to indicate what "mode" your class is in (input mode or output mode).
Also, I don't understand the point of:
var outputPanel = new OutputPanel();
bodyControl = outputPanel();
I think it should read bodyControl = outputPanel; the same way bodyControl = inputPanel;

How can I make sure only one WPF Window is open at a time?

I have a WPF window that I am launching from inside of a winform app. I only want to allow once instance of that WPF window to be open at a time, and not warn that user if they try to open it again.
I am having a problem however trying to search for that WPF window being open because the window is being launched from a winform. What I normaly do is when searching for a winform, I search for any instances of that winform existing in the Application.Current.OpenForms, and when in WPF I search for Application.Current.Windows
The problem I have is that System.Windows.Application.Current is null when launched from inside of a winform, so I can't search for the WPF window that way. Is there any better way of searching for an existing instance of an open window?
My Code:
if (System.Windows.Application.Current != null)
{
foreach (System.Windows.Window win in System.Windows.Application.Current.Windows)
{
if (win is frmCaseWpf)
{
MessageBox.Show("You may have only one active case open at a time.", "Open Case",
MessageBoxButtons.OK,
MessageBoxIcon.Stop);
win.WindowState = System.Windows.WindowState.Normal;
win.Focus();
win.Activate();
return;
}
}
}
Instead of searching the static application objects, you could instead just track this within your window, with a single static variable. Just keep a variable in the window:
private static frmCaseWpf openWindow = null; // Assuming your class name is frmCaseWpf
When you create a window, either in the initialize routines, or OnLoaded, depending on how you want it to work..:
partial class frmCaseWpf {
public frmCaseWpf {
this.OnLoaded += frmCaseWpf_OnLoaded;
}
private void frmCaseWpf_OnLoaded(object sender, RoutedEventArgs e)
{
if (this.openWindow != null)
{
// Show message box, active this.openWindow, close this
}
this.openWindow = this;
}
}
If you want this window to be reusable, make sure to set this.openWindow = null; when you close the window, as well.
Here's something that's working for me.
private About aboutWin;
private void AboutOpenClicked(object sender, RoutedEventArgs e)
{
if(aboutWin == null)
{
aboutWin = new About();
aboutWin.Closed += (a, b) => aboutWin = null;
aboutWin.Show();
}
else
{
aboutWin.Show();
}
}
It would be better make the frmCaseWpf class a singleton. That way you can't create another instance
Rather than try to search for a Window instance, many people use a session- (or system-) wide "Mutex" or a Mutual Exclusion lock. I was going to rewrite one for you, but I found a good codeproject article demonstrating the technique. It's not complex and very simple.
http://www.codeproject.com/KB/cs/SingleInstanceAppMutex.aspx?msg=2908697
Sneak peek:
[STAThread]
static void Main()
{
bool onlyInstance = false;
Mutex mutex = new Mutex(true, "UniqueApplicationName", out onlyInstance);
if (!onlyInstance) {
return;
}
Application.Run(new MainForm);
GC.KeepAlive(mutex);
}
Hope this helps.
(edit: of course you'll have to modify this slightly for your particular use-case, but it demos the general idea)
I am not really a 'proper' programmer, however I have achieved this in a WPF application (not from a winforms one) by using the following:
Dim wdwDetails As New detailsNew()
Private Sub openNewDetails(ByVal recordID As String)
wdwDetails.Owner = Me
wdwDetails.recordID = recordID
wdwDetails.WindowStartupLocation = Windows.WindowStartupLocation.CenterOwner
wdwDetails.Show()
End Sub
Essentially because I am creating the window object outside of the sub that opens it, there will only be a single window. Any new call to the window open sub will use the same object. But I guess that is what Thomas is referring to also.
Like I said, not sure if this will help you or not though.
You can use XXXwindown.isLoad to check if window is loaded before you create a new window:
if ( !ChildWindow.IsLoaded)
{
childWindow= new ChildWindow();
childWindow.Show();
}

Categories

Resources