-2

Note: Because my question got flagged as duplicate, here some more details: Is there a way to encapsulate the code, without writing it x-times for every class? (It's not about the MainWindow! It's about multiple window classes!)

My WPF-Application contains multiple Windows (e.g. Win1, Win2, Win3, ..). I want that some of them can't open multiple instances at the same time. So let's say if Win1 is allready open and the user clicks for a new Window, I will bring the Win1 (which is still open) to the front of the UI. It is also needed that it's possible to have multiple (but different Windows open) like Win1 and Win2 are open at the same time!

I solved it with this approach in the Win1-class:

    private static Win1 openWindow = null;

In the OnLoaded-Event:

private void Window_Loaded(object sender, RoutedEventArgs e)
    {

        if (Win1.openWindow != null)
        {
            Win1.openWindow.Topmost = true;
            if (Win1.openWindow.WindowState == WindowState.Minimized)
                Win1.openWindow.WindowState = System.Windows.WindowState.Normal;
            Win1.openWindow.Activate();
            Win1.openWindow.Topmost = false;
            this.Close();
        }
        else Win1.openWindow = this;

And finally in the OnClosing-Event:

    private void Window_Closing(object sender, CancelEventArgs e)
    {
       if (Win1.openWindow == this)
           Win1.openWindow = null;
    }

I need this behavoir in like 20 other Win-classes. Is there a better way how I could implement it, without adding it 20-times per hand? I tried to write a custom Window class and use it for inheritance, but the static field needs the specific type (e.g. Win1).

Any advices welcome!

Thank you

wulf11
  • 79
  • 8
  • If each window is a unique type then you can use `Application.Current.Windows.OfType()' to find any existing window of type Win1? Either way I would suggest that you need some check in the code that is creating the new windows rather than in the window itself. – Ben Bancroft Sep 05 '19 at 11:19
  • hmm it would be possible that I store all active Windows in a List and filter it with your suggestion! But I am still not sure how to design it without writing the code too often in different places – wulf11 Sep 05 '19 at 11:21
  • If you had code like `Win1 window = new Win1()` I would just wrap it with `if(!Application.Current.Windows.OfType().Any()) { Win1 window = new Win1(); }`, i.e. the new window would only be created if the application didn't already contain a window of that type. Or you could do `Win1 window = Application.Current.Windows.OfType().FirstOrDefault(); if(window == null) { window = new Win1; }` – Ben Bancroft Sep 05 '19 at 11:31
  • thanks so far! but this still means I have to wrap it everytime I create a new instance right? So I still need it like 20 times..My hope was that there was some pattern I could use to write the check only once :) – wulf11 Sep 05 '19 at 11:36
  • You use the Win1.openWindow other way then checking if is open? If no, I have one extension method that can do that – Kevin Kouketsu Sep 05 '19 at 11:38
  • I guess I am misunderstanding your requirements but I think you could wrap that code in a static method. If I get chance I will create a demo for you. – Ben Bancroft Sep 05 '19 at 11:40
  • every example is welcome! Someone flagged the question as duplicate, guess my description was not on point.. – wulf11 Sep 05 '19 at 11:45
  • Are you sure you don't want to be using a tab control? Because that seems like the type of application you are creating in essence. – Kevin Cook Sep 05 '19 at 12:30
  • unfortunately I need multiple windows open at the same time and some of them are allowed to have multiple instances , others don't :( but good hint anyways.. – wulf11 Sep 05 '19 at 12:33
  • 2
    @wulf11 I was thinking something like [this](https://github.com/glrad/OnlyOneOfEachTypeOfWindow) – Ben Bancroft Sep 05 '19 at 12:34
  • @ Ben Bancroft! Your example is excactly what I wanted! You may post the code for the WindowManager as anwere so that I can give you the reputation you deserve :) – wulf11 Sep 05 '19 at 13:00
  • For future reference, this is the `Factory` design pattern. I.e. when you need a certain object, don't create one yourself. Instead, you request it from a Factory (in this example, the `WindowManager`). The rest of the code only cares about getting an object (e.g. Win1). The Factory can decide whether to make a new one, or in your case, give you an existing instance. In the future, if you actually change your mind and may want some windows that can have more than one instance, you just modify the Factory without touching the rest of your code. – NPras Sep 06 '19 at 03:26
  • heard about Factorys before and will take a deeper look now! thank you for pointing this out! – wulf11 Sep 06 '19 at 05:31

1 Answers1

0

The solution was provided by @Ben Bancroft in his example here:
OnlyOneOfEachTypeOfWindow-Example

As @NPras told me, it uses the Factory-Pattern to solve the problem, mainly with the class here:

public static class WindowManager
{
    public static T GetWindow<T>()
    {
        var t = Application.Current.Windows.OfType<T>().FirstOrDefault();
        if (t == null)
        {
            t = (T)Activator.CreateInstance(typeof(T));
        }
        return t;
    }

    public static T CreateOrFocusWindow<T>()
    {
        var t = GetWindow<T>();
        if (t is Window)
        {
            var window = t as Window;
            if (window.Visibility != Visibility.Visible)
                window.Show();
            if (window.WindowState == WindowState.Minimized)
                window.WindowState = WindowState.Normal;
            window.Focus();
        }
        return t;
    }
}

You can then use it like:

var window = WindowManager.CreateOrFocusWindow<Window1>();
var window = WindowManager.CreateOrFocusWindow<Window2>();

Thanks for the help!

wulf11
  • 79
  • 8