在我的 WPF 应用程序中,我想订阅一些事件/callbeck/whatever 来告诉我每当我的应用程序中的对话框窗口打开(和关闭)时。
我找到了窗口集合,但这是一个简单的容器,它似乎没有提供任何订阅方式。
我也尝试使用事件处理程序,但似乎没有一个事件告诉我我需要什么。
有任何想法吗?
在我的 WPF 应用程序中,我想订阅一些事件/callbeck/whatever 来告诉我每当我的应用程序中的对话框窗口打开(和关闭)时。
我找到了窗口集合,但这是一个简单的容器,它似乎没有提供任何订阅方式。
我也尝试使用事件处理程序,但似乎没有一个事件告诉我我需要什么。
有任何想法吗?
如果没有为所有窗口创建一个基类,您可以在其中挂钩打开的事件(或手动将打开的事件添加到每个窗口),我不确定您如何知道何时创建新窗口。
可能有一种更优雅的方式,但您可以轮询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 毫秒。
在没有基类的情况下执行此操作的一种方法是将处理程序添加到 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);
}
您可以在 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);
}
上面的链接似乎在实例上注册了一个空处理程序以使事情正常工作。
我从未听说过任何全球性的开/关事件。
应该以某种方式可以做到,但这提供了您可以控制所有窗口的打开和关闭。就像您构建一个所有对话框窗口都继承自的“基本窗口”(自然继承“窗口”)一样。
然后你会在“基本窗口”上有一个静态事件,你从基本窗口的打开和关闭/关闭(或卸载)事件中触发,将“this”作为“sender”发送。您可以在 App.xaml.cs 类中附加到该静态事件。
这是一个黑客,但它是可能的。