1

在我的 WPF 应用程序中,我想订阅一些事件/callbeck/whatever 来告诉我每当我的应用程序中的对话框窗口打开(和关闭)时。

我找到了窗口集合,但这是一个简单的容器,它似乎没有提供任何订阅方式。

我也尝试使用事件处理程序,但似乎没有一个事件告诉我我需要什么。

有任何想法吗?

4

4 回答 4

1

如果没有为所有窗口创建一个基类,您可以在其中挂钩打开的事件(或手动将打开的事件添加到每个窗口),我不确定您如何知道何时创建新窗口。

可能有一种更优雅的方式,但您可以轮询Application.Current.Windows以查看是否创建了任何新窗口,同时跟踪您找到的窗口。

这是一个粗略的示例,它将演示如何使用 aDispatchTimer来轮询新窗口、跟踪找到的窗口并挂钩到关闭的事件。

代码背后

public partial class MainWindow : Window
{
    private DispatcherTimer Timer { get; set; }

    public ObservableCollection<Window> Windows { get; private set; }

    public MainWindow()
    {
        InitializeComponent();

        // add current Window so we don't add a hook into it
        Windows = new ObservableCollection<Window> { this };

        Timer = new DispatcherTimer( DispatcherPriority.Background );
        Timer.Interval = TimeSpan.FromMilliseconds( 500 );
        Timer.Tick += ( _, __ ) => FindNewWindows();
        Timer.Start();

        this.WindowListBox.ItemsSource = Windows;
        this.WindowListBox.DisplayMemberPath = "Title";
    }

    private void FindNewWindows()
    {
        foreach( Window window in Application.Current.Windows )
        {
            if( !Windows.Contains( window ) )
            {
                window.Closed += OnWatchedWindowClosed;
                // inserting at 0 so you can see it in the ListBox
                Windows.Insert( 0, window );
                Feedback.Text = string.Format( "New Window Found: {0}\r\n{1}",
                                                window.Title, Feedback.Text );
            }
        }
    }

    private void OnWatchedWindowClosed( object sender, EventArgs e )
    {
        var window = (Window)sender;
        Windows.Remove( window );
        Feedback.Text = string.Format( "Window Closed: {0}\r\n{1}",
                                        window.Title, Feedback.Text );
    }

    private void CreateWindowButtonClick( object sender, RoutedEventArgs e )
    {
        string title = string.Format( "New Window {0}", DateTime.Now );
        var win = new Window
                    {
                            Title = title,
                            Width = 250,
                            Height = 250,
                            Content = title,
                    };

        win.Show();
        e.Handled = true;
    }
}

XAML

<Grid>
    <ListBox Name="WindowListBox"
                Width="251"
                Height="130"
                Margin="12,12,0,0"
                HorizontalAlignment="Left"
                VerticalAlignment="Top" />
    <TextBox Name="Feedback"
                Width="479"
                Height="134"
                Margin="12,148,0,0"
                HorizontalAlignment="Left"
                VerticalAlignment="Top"
                VerticalScrollBarVisibility="Auto" />
    <Button Name="CreateWindowButton"
            Width="222"
            Height="130"
            Margin="269,12,0,0"
            HorizontalAlignment="Left"
            VerticalAlignment="Top"
            Click="CreateWindowButtonClick"
            Content="Create New Window"
            FontSize="20" />
</Grid>

单击并创建任意数量的新窗口;然后关闭它们。你会看到反馈,因为它发生。当然,每当创建新窗口时都会有 500 毫秒的延迟,因为DispatchTimer' 的间隔设置为 500 毫秒。

于 2012-12-15T22:22:56.687 回答
1

在没有基类的情况下执行此操作的一种方法是将处理程序添加到 MainWindow deactivated

如果打开一个新窗口,主窗口将失去焦点 = 你的“新窗口事件”

private readonly List<Window> openWindows = new List<Window>();

public void ApplicationMainWindow_Deactivated(object sender, EventArgs e)
{
    foreach (Window window in Application.Current.Windows)
    {
        if (!openWindows.Contains(window) && window != sender)
        {
            // Your window code here
            window.Closing += PopupWindow_Closing;
            openWindows.Add(window);
        }
    }
}

private void PopupWindow_Closing(object sender, CancelEventArgs e)
{
    var window = (Window)sender;
    window.Closing -= PopupWindow_Closing;
    openWindows.Remove(window);
}
于 2017-08-21T13:32:23.983 回答
1

您可以在 App.cs 中注册一个类处理程序,如此处所示

https://gist.github.com/mwisnicki/3104963

    ...
    EventManager.RegisterClassHandler(typeof(UIElement), FrameworkElement.LoadedEvent, new RoutedEventHandler(OnLoaded), true);
    EventManager.RegisterClassHandler(typeof(UIElement), FrameworkElement.UnloadedEvent, new RoutedEventHandler(OnUnloaded), true);
    ...        

    private static void OnLoaded(object sender, RoutedEventArgs e)
    {
        if (sender is Window)
            Console.WriteLine("Loaded Window: {0}", sender);
    }

    private static void OnUnloaded(object sender, RoutedEventArgs e)
    {
        if (sender is Window)
            Console.WriteLine("Unloaded Window: {0}", sender);
    }

上面的链接似乎在实例上注册了一个空处理程序以使事情正常工作。

于 2018-08-14T15:45:18.907 回答
0

我从未听说过任何全球性的开/关事件。

应该以某种方式可以做到,但这提供了您可以控制所有窗口的打开和关闭。就像您构建一个所有对话框窗口都继承自的“基本窗口”(自然继承“窗口”)一样。

然后你会在“基本窗口”上有一个静态事件,你从基本窗口的打开和关闭/关闭(或卸载)事件中触发,将“this”作为“sender”发送。您可以在 App.xaml.cs 类中附加到该静态事件。

这是一个黑客,但它是可能的。

于 2012-12-15T17:51:23.047 回答