私の WPF アプリケーションでは、アプリケーションでダイアログ ウィンドウが開く (および閉じる) たびに、イベント/callbeck/何かにサブスクライブしたいと考えています。
ウィンドウ コレクションを見つけましたが、これは単純なコンテナーであり、サブスクリプションの手段を提供していないようです。
イベントハンドラーも使用してみましたが、必要なものを教えてくれるイベントがないようです。
何か案は?
私の WPF アプリケーションでは、アプリケーションでダイアログ ウィンドウが開く (および閉じる) たびに、イベント/callbeck/何かにサブスクライブしたいと考えています。
ウィンドウ コレクションを見つけましたが、これは単純なコンテナーであり、サブスクリプションの手段を提供していないようです。
イベントハンドラーも使用してみましたが、必要なものを教えてくれるイベントがないようです。
何か案は?
基本クラスなしでそれを行う 1 つの方法は、無効化された MainWindow にハンドラーを追加することです。
新しいウィンドウが開かれると、メイン ウィンドウはフォーカスを失います = 「新しいウィンドウ イベント」
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
を使用して新しいウィンドウをポーリングし、見つかったウィンドウを追跡し、closed イベントにフックする方法を示す大まかな例を次に示します。
コードビハインド
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>
クリックして、必要な数の新しいウィンドウを作成します。それらを閉じます。フィードバックが発生したときに表示されます。DispatchTimer
確かに、の間隔が 500 ミリ秒に設定されているため、新しいウィンドウが作成されるたびに 500 ミリ秒の遅延が発生します。
グローバルな開閉イベントは聞いたことがありません。
何とかできるはずですが、それはすべてのウィンドウの開閉を制御できることを意味します。すべてのダイアログウィンドウが継承する「ベースウィンドウ」(「ウィンドウ」を自然に継承する)を構築する場合と同様です。
次に、「ベース ウィンドウ」に静的イベントを設定します。このイベントは、ベース ウィンドウの開始および終了/終了 (またはアンロード) イベントから起動し、「送信者」として「this」を送信します。App.xaml.cs クラスでその静的イベントにアタッチできます。
ハックですが、可能です。