在我的WPF应用程序中,我想订阅一些事件/callbeck/任何告诉我的事件/callbeck/任何内容,每当我的应用程序中的对话框窗口打开(和关闭)时。
我找到了窗口集合,但这是一个简单的容器,它似乎不提供任何订阅方式。
我也尝试使用事件处理程序,但似乎没有一个事件告诉我我需要什么。
有什么想法吗?
在没有基类的情况下执行此操作的一种方法是将处理程序添加到停用的主窗口
如果打开一个新窗口,主窗口将失去焦点=您的"新窗口事件"
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);
}
如果不为所有窗口创建一个基类,您可以在其中挂接到打开的事件(或手动将打开的事件添加到每个窗口),我不确定您如何能够知道何时创建新窗口。
可能有一种更优雅的方法,但您可以轮询Application.Current.Windows
以查看是否创建了任何新窗口,同时跟踪您找到的窗口。
下面是一个粗略的示例,它将演示如何使用DispatchTimer
轮询新窗口,跟踪找到的窗口并挂钩到已关闭的事件。
代码隐藏
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}rn{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}rn{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>
单击并根据需要创建任意数量的新窗口;然后关闭它们。您将在反馈发生时看到反馈。当然,每当创建新窗口时,都会有500ms的延迟,因为DispatchTimer
的间隔设置为500ms。
您可以在 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"作为"发送者"发送。可以在 App.xaml.cs 类中访问该静态事件。
这是一个黑客,但这是可能的。