The Artima Developer Community
Sponsored Link

.NET Buzz Forum
WPF: Offene Fenster im Überblick behalten

0 replies on 1 page.

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 0 replies on 1 page
-

Posts: 1524
Nickname: nitronic
Registered: Jul, 2006

Norbert Eder works as a software architect.
WPF: Offene Fenster im Überblick behalten Posted: Jun 22, 2008 11:39 AM
Reply to this message Reply

This post originated from an RSS feed registered with .NET Buzz by -.
Original Post: WPF: Offene Fenster im Überblick behalten
Feed Title: Norbert Eder - Living .NET
Feed URL: http://feeds.feedburner.com/NorbertEder-Livingnet
Feed Description: Copyright (c)2005, 2006 by Norbert Eder
Latest .NET Buzz Posts
Latest .NET Buzz Posts by -
Latest Posts From Norbert Eder - Living .NET

Advertisement
Wir kennen es wohl alle: Das "Window"-Menü mit allen offenen Fenstern derselben Applikation. Vor allem in den Office-Produkten war dies immer wieder zu finden. Doch wie kann dies unter WPF implementiert werden? Dieser Artikel zeigt wie's geht. Und so kann das Endresultat aussehen (es ist zwar nicht hübsch, aber es funktioniert):



Zu Beginn stellt sich natürlich dir Frage ob es da nicht schon etwas Fertiges gibt. Ja. Gibt es. Unter Application.Current.Windows findet sich die aktuelle Auflistung aller geöffneten Fenster. Einziger Nachteil: Diese stecken in einer eigenen WindowCollection, welche lediglich ICollection und IEnumerable implementiert. Damit jedoch Data Binding möglich ist, wäre eine ObservableCollection notwendig.

Damit es uns Entwicklern nicht fad wird, müssen wir daher selbst in die Tasten klopfen und unser eigenes System entwickeln, wollen wir doch Data Binding verwenden!

Zuerst benötigen wir eine simple Datenklasse, welche Informationen für uns hält und auch später wieder zugänglich macht:
public class WindowInformation
{
    private Window _window; 

    public WindowInformation(Window window)
    {
        _window = window;
    }

    public Window Window
    {
        get { return _window; }
    }

    public int WindowHashCode 
    {
        get { return _window.GetHashCode(); }
    }

    public String Title
    {
        get { return _window.Title; }
    }

    public ImageSource Icon
    {
        get { return _window.Icon; }
    }
}

Die Datenklasse fungiert in diesem Fall lediglich als Wrapper-Klasse, könnte aber ohne großen Aufwand um weitere Informationen angereichert werden.

Damit nun Data Binding verwendet werden kann, benötigen wir eine - wie schon angesprochen - ObserableCollection:
public class WindowInformationCollection : 
    ObservableCollection<WindowInformation>
{
}

Nun wird eine Manager-Klasse benötigt, welche die Liste der geöffneten Fenster hält und zusätzliche Funktionen wie Entfernen eines Fensters oder das Zurückgeben eines speziellen Fensters zur Verfügung stellt. Dieser Manager wurde mit dem Singleton-Pattern umgesetzt, damit sichergestellt ist, dass nur eine Instanz davon pro gestarteter Anwendungsinstanz vorhanden ist.
public class WindowManager
{
    private static WindowManager _manager;

    private WindowInformationCollection _openWindows = 
        new WindowInformationCollection();

    private WindowManager() { }

    public static WindowManager GetInstance
    {
        get
        {
            if (_manager == null)
                _manager = new WindowManager();
            return _manager;
        }
    }

    public WindowInformationCollection OpenWindows
    {
        get { return _openWindows; }
    }

    public Window GetOpenWindow(int hashCode)
    {
        foreach (WindowInformation wi in _openWindows)
        {
            if (wi.WindowHashCode == hashCode)
            {
                return wi.Window;
            }
        }
        return null;
    }

    public bool RemoveOpenWindow(int hashCode)
    {
        WindowInformation windowToRemove = null;
        foreach (WindowInformation wi in _openWindows)
        {
            if (wi.WindowHashCode == hashCode)
            {
                windowToRemove = wi;
                break;
            }
        }
        if (windowToRemove != null)
        {
            _openWindows.Remove(windowToRemove);
            return true;
        }
        return false;
    }
}

Zu guter Letzt wird noch ein Handler implementiert, der schlussendlich in das Window-Element des XAMLs eingebunden werden kann und somit ein Fenster in das System einbindet:
public class WindowInformationHandler
{
    public static readonly DependencyProperty 
        IsHandledProperty =
    DependencyProperty.RegisterAttached("IsHandled", 
        typeof(bool), typeof(WindowInformationHandler),
        new FrameworkPropertyMetadata((bool)false,
            new PropertyChangedCallback(OnIsHandledChanged)));

    private static void OnIsHandledChanged(
        DependencyObject dObj, 
        DependencyPropertyChangedEventArgs e)
    {
        Window openWindow = dObj as Window;
        if (openWindow != null)
        {
            openWindow.Loaded += 
                new RoutedEventHandler(WindowLoaded);
            openWindow.Closed += 
                new EventHandler(WindowClosed);
        }
    }

    public static bool GetIsManaged(DependencyObject dObj)
    {
        return (bool)dObj.GetValue(IsHandledProperty);
    }

    public static void SetIsManaged(
        DependencyObject dObj, 
        bool value)
    {
        dObj.SetValue(IsHandledProperty, value);
    }

    private static void WindowClosed(
        object sender, EventArgs e)
    {
        Window closedWindow = sender as Window;
        if (closedWindow != null)
        {
            WindowManager.GetInstance.RemoveOpenWindow(
                closedWindow.GetHashCode()
                );
            openWindow.Loaded -= 
                new RoutedEventHandler(WindowLoaded);
            openWindow.Closed -= 
                new EventHandler(WindowClosed);
        }
    }

    private static void WindowLoaded(
        object sender, RoutedEventArgs e)
    {
        Window openWindow = sender as Window;
        if (openWindow != null)
        {
            WindowInformation winInfo = 
                new WindowInformation(openWindow);
            WindowManager.GetInstance.OpenWindows.Add(winInfo);
        }
    }
}

Wird die Eigenschaft IsHandled auf true gesetzt, werden zwei Events (Loaded und Closed) registriert. Auf diese wird in weiterer Folge reagiert, um das Fenster nach erfolgtem Laden in die Liste der geöffneten Fenster aufzunehmen bzw. davon auch wieder zu entfernen.

In XAML wird dies folgendermaßen in das Window-Element eingebunden:
local:WindowInformationHandler.IsManaged="true"

Damit ist dieses System fertig und kann angewandt werden.

Das XAML-Markup für oben gezeigten Screenshot sieht so aus:

Und hier noch der Inhalt aus dem Code Behind:
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        mnuWindows.ItemsSource = 
            WindowManager.GetInstance.OpenWindows;
    }

    private void NewWindow(object sender, 
        RoutedEventArgs e)
    {
        MainWindow window = new MainWindow();
        window.Title = String.Format("Open Window {0}", 
            Application.Current.Windows.Count);
        window.Show();
    }

    private void ShowWindow(object sender, 
        RoutedEventArgs e)
    {
        MenuItem mi = sender as MenuItem;
        if (mi != null)
        {
            WindowInformation wi = mi.DataContext 
                as WindowInformation;
            if (wi != null)
            {
                wi.Window.Focus();
            }
        }
    }
}

Voilá!

Read: WPF: Offene Fenster im Überblick behalten

Topic: Samsung Omnia i900 Previous Topic   Next Topic Topic: Silverlight 1 and Firefox 3

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use