Pertanyaan Aplikasi WPF kehilangan fokus sepenuhnya pada penutupan jendela


Deskripsi masalah

Jika saya membuat jendela non-modal sebagai jendela anak melalui pengaturan Pemilik jendela ke jendela induk, dan kemudian menampilkan MessageBox dari dalam jendela anak ini, jendela induk akan kehilangan fokus jika saya menutup jendela anak. Jika windows explorer atau aplikasi lain terbuka, aplikasi ini akan mendapatkan fokus dan jendela utama saya akan disembunyikan.

Hal ini tampaknya menjadi masalah yang diketahui saat saya melihatnya di tempat lain newsgroup, tetapi saya belum melihat solusi yang baik. Mengatur pemilik ke null di OnDeactivate bukan merupakan opsi. Mengatur pemilik sebelum menampilkan Kotak Pesan ke nol dan mengatur ulang setelah itu tidak membantu. Mengatur pemilik ke null dalam acara OnClosed juga tidak membantu.

Solusi Sederhana ditemukan

Jika Anda mengalami masalah yang sama seperti yang saya jelaskan, letakkan kode berikut di jendela OnClosing of all child.

void  OnClosing(System.ComponentModel.CancelEventArgs e)
  base.OnClosing(e);
  if (null != Owner) {
         Owner.Activate();
  }
  // ....

Ini dapat diikuti oleh logika pemrosesan lebih lanjut, bahkan membuka MessageBoxes ditoleransi.

Kode-Contoh

Masalahnya tampaknya jauh lebih besar seperti yang saya pikirkan. Contoh berikut akan menghapus fokus dari jendela induk jika kotak pesan akan dibuka dan jendela anak akan ditutup (Salin kode ke dalam event-handler Window yang dimuat).

Window firstChildWindow = new Window() {
    Title = "Floating Window", Width = 100, Height = 70
};
firstChildWindow.Owner = Window.GetWindow(this);

Button button = new Button() { Content="MessageBox"};
button.Click += delegate { 
    MessageBox.Show("Klicking her breaks the focus-chain."); };
firstChildWindow.Content = button;
firstChildWindow.Show();

Juga contoh ini memecah rantai fokus:

Window firstChildWindow = new Window() {
    Title = "Floating Window", Width = 100, Height = 70
};
firstChildWindow.Owner = Window.GetWindow(this);
firstChildWindow.Show();

Window secondChildWindow = new Window() { 
    Title="Second Window",Width=100,Height=70};
secondChildWindow.Content = new TextBlock() { 
    Text="SecondWindow"};
secondChildWindow.Owner = firstChildWindow;
secondChildWindow.Show();

Memiliki seseorang resolusi untuk masalah ini. Saya berpikir tentang hack untuk memicu memberikan fokus kepada orang tua setelah penutupan, dengan Dispatcher atau DispachterTimer atau mungkin itu akan bekerja untuk fokus kekuatan manual ke induk pada tutup tetapi ini semua bagi saya sangat najis (dan juga sedikit rumit jika ada lebih banyak jendela yang dimiliki oleh orang tua yang sama, seperti yang saya miliki di aplikasi saya saat ini).

Tidak ada yang tahu solusi yang rapi untuk ini?

Sumber daya

Deskripsi MSDN (lihat di bawah komentar untuk jendela non modal dibuka memanggil Show ())

Masalah yang sama di forum msdn tanpa solusi yang tepat

Silakan lihat juga: Fokus yang tidak stabil dari aplikasi WPF


32
2018-06-29 21:02


asal


Jawaban:


Apa yang paling mungkin terjadi di sini adalah Anda memiliki dua jendela tingkat atas independen dan menutup salah satunya. Ini terkadang akan menyebabkan fokus untuk melompat ke aplikasi lain.

Ini juga terjadi jika satu jendela memiliki kedua, yang pada gilirannya memiliki ketiga. Mungkin BUG di Win32 API tetapi sudah bersama kami selamanya jadi semoga berhasil memperbaikinya.

Solusinya adalah secara manual menyerahkan fokus kembali ke anak dalam acara Penutupan cucu. Tetapi dalam kasus ini, cucu adalah messagebox sehingga Anda tidak bisa melakukan itu. Hal termudah untuk dilakukan adalah memiliki messagebox ke orang tua. Cara termudah berikutnya adalah membuat kontrol messagebox Anda sendiri.


22



Ini adalah bug yang sangat mengganggu, solusi paling umum yang disediakan adalah:

panggilan Me.Owner.Focus dalam Window_Unloaded atau Window_Closing peristiwa.

Tapi itu masih tidak berfungsi 100%, Anda masih melihat jendela latar belakang berkedip ke latar depan (sangat singkat), sebelum fokus dipulihkan dengan benar.

Saya menemukan metode yang berfungsi lebih baik:

panggilan Me.Owner.Activatesebelum Me.Close (atau di _Closing peristiwa).


20



Mungkin saya cukup terlambat dalam masalah ini.
@HCL masalah ini dapat diselesaikan dengan lebih mudah dengan mengatur pilihan parameter dari MessageBox.show () untuk MessageBoxOptions.None.

Tepuk tangan...


2



adalah mungkin untuk menulis kotak pesan Anda sendiri, Anda dapat menerapkannya sebagai pelampung yang menonaktifkan seluruh layar ketika ditampilkan.

Anda memeriksa sampel framegm mtvm kalibrasi, ada implementasi yang bagus dari messagebox sebagai layanan.


0



Kepemilikan tidak ada hubungannya dengan aktivasi jendela. Untuk melihat ini, ubah pemilik jendela kedua ke jendela atas dan jalankan program. Perhatikan bahwa tidak ada yang berubah. Kepemilikan harus dilakukan dengan "Jika jendela diminimalkan, apa yang perlu diminimalkan oleh jendela lain". Jadi Anda terjebak dengan menggunakan kode aktivasi khusus.


0



Solusi Johsua's .Activate (lihat di atas) bekerja dengan baik dengan segala jenis window. Setidaknya itu berhasil bagiku.


0



saya memiliki masalah serupa. Saya memiliki satu jendela utama, di mana jendela anak kecil ditempatkan ke jendela itu melalui properti Pemilik. Jika jendela utama memiliki dua atau lebih anak, setelah menutup anak kedua, aplikasi kehilangan fokus. Saya menggunakan trik dengan child.Owner = null sebelum tutup, tetapi kemudian jendela anak saya berikutnya kehilangan fokus. Saya menanganinya dengan mendapatkan semua anak dan mengatur fokus ke yang terakhir sebelum menutup anak. Berikut ini contoh kode:

private void OnClosing(object sender, CancelEventArgs cancelEventArgs)
        {
            var childWindows = (sender as Window).Owner.OwnedWindows;
            if (childWindows.Count - 2 >= 0)
                childWindows[childWindows.Count - 2].Focus();
            else
            {
                (sender as Window).Owner.Focus();
            }
            (sender as Window).Owner = null;
        }

0