Saya perlu mencari hierarki kontrol WPF untuk kontrol yang cocok dengan nama atau tipe yang diberikan. Bagaimana saya bisa melakukan ini?
Saya menggabungkan format template yang digunakan oleh John Myczek dan algoritma Tri Q di atas untuk membuat Algoritma findChild yang dapat digunakan pada orangtua mana pun. Perlu diingat bahwa pencarian pohon secara rekursif ke bawah bisa menjadi proses yang panjang. Saya hanya memeriksa ini di aplikasi WPF, beri komentar tentang kesalahan yang mungkin Anda temukan dan saya akan memperbaiki kode saya.
WPF Snoop adalah alat yang berguna dalam melihat pohon visual - Saya sangat merekomendasikan menggunakannya saat menguji atau menggunakan algoritma ini untuk memeriksa pekerjaan Anda.
Ada kesalahan kecil dalam Algoritma Tri Q. Setelah anak ditemukan, jika childrenCount> 1 dan kita mengulangi lagi kita dapat menimpa anak yang ditemukan dengan benar. Karena itu saya menambahkan if (foundChild != null) break;
kode saya untuk menangani kondisi ini.
/// <summary>
/// Finds a Child of a given item in the visual tree.
/// </summary>
/// <param name="parent">A direct parent of the queried item.</param>
/// <typeparam name="T">The type of the queried item.</typeparam>
/// <param name="childName">x:Name or Name of child. </param>
/// <returns>The first parent item that matches the submitted type parameter.
/// If not matching item can be found,
/// a null parent is being returned.</returns>
public static T FindChild<T>(DependencyObject parent, string childName)
where T : DependencyObject
{
// Confirm parent and childName are valid.
if (parent == null) return null;
T foundChild = null;
int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < childrenCount; i++)
{
var child = VisualTreeHelper.GetChild(parent, i);
// If the child is not of the request child type child
T childType = child as T;
if (childType == null)
{
// recursively drill down the tree
foundChild = FindChild<T>(child, childName);
// If the child is found, break so we do not overwrite the found child.
if (foundChild != null) break;
}
else if (!string.IsNullOrEmpty(childName))
{
var frameworkElement = child as FrameworkElement;
// If the child's name is set for search
if (frameworkElement != null && frameworkElement.Name == childName)
{
// if the child's name is of the request name
foundChild = (T)child;
break;
}
}
else
{
// child element found.
foundChild = (T)child;
break;
}
}
return foundChild;
}
Sebut saja seperti ini:
TextBox foundTextBox =
UIHelper.FindChild<TextBox>(Application.Current.MainWindow, "myTextBoxName");
Catatan Application.Current.MainWindow
dapat berupa jendela induk.
FrameworkElement
sebagai T, itu akan mengembalikan nol segera setelah loop pertama berakhir. jadi Anda perlu melakukan beberapa modifikasi.Anda juga dapat menemukan elemen dengan nama menggunakan FrameworkElement.FindName (string) .
Diberikan:
Dalam file kode-belakang, Anda dapat menulis:
Tentu saja, karena didefinisikan menggunakan x: Name, Anda bisa mereferensikan bidang yang dihasilkan, tetapi mungkin Anda ingin mencarinya secara dinamis daripada statis.
Pendekatan ini juga tersedia untuk template, di mana item bernama muncul beberapa kali (sekali per penggunaan template).
sumber
Anda dapat menggunakan VisualTreeHelper untuk menemukan kontrol. Di bawah ini adalah metode yang menggunakan VisualTreeHelper untuk menemukan kontrol induk dari tipe tertentu. Anda dapat menggunakan VisualTreeHelper untuk menemukan kontrol dengan cara lain juga.
Sebut saja seperti ini:
sumber
Saya mungkin hanya mengulangi semua orang tetapi saya memiliki sepotong kode cantik yang memperluas kelas DependencyObject dengan metode FindChild () yang akan memberi Anda anak berdasarkan jenis dan nama. Cukup sertakan dan gunakan.
Semoga bermanfaat.
sumber
Ekstensi saya ke kode.
Sumber: https://code.google.com/p/gishu-util/source/browse/#git%2FWPF%2FUtilities
Posting blog penjelasan: http://madcoderspeak.blogspot.com/2010/04/wpf-find-child-control-of-specific-type.html
sumber
Jika Anda ingin menemukan SEMUA kontrol dari jenis tertentu, Anda mungkin tertarik dengan cuplikan ini juga
sumber
child
yang kedua kalinya? Jika Anda memilikichildType
tipeT
, Anda dapat menulis di dalamif
:yield return childType
... tidak?Ini akan mengabaikan beberapa elemen - Anda harus memperluasnya seperti ini untuk mendukung beragam kontrol. Untuk diskusi singkat, lihat di sini
sumber
Try*
metode untuk kembalibool
dan memilikiout
parameter yang kembali jenis yang bersangkutan, seperti:bool IDictionary.TryGetValue(TKey key, out TValue value)
FindParent
. Nama ini bagi saya menyiratkan bahwa itu bisa kembalinull
. TheTry*
prefix digunakan di seluruh BCL dengan cara saya jelaskan di atas. Perhatikan juga bahwa sebagian besar jawaban lain di sini menggunakanFind*
konvensi penamaan. Ini hanya poin kecil :)Saya mengedit kode CrimsonX karena tidak bekerja dengan jenis superclass:
sumber
DependencyObject
, ini bukan metodeFrameworkElement
yang dapat membuang Pengecualian. Juga menggunakanGetChildrenCount
pada setiap iterasi darifor
loop terdengar seperti ide yang buruk.Sementara saya suka rekursi secara umum, itu tidak seefisien iterasi ketika pemrograman dalam C #, jadi mungkin solusi berikut ini lebih rapi daripada yang disarankan oleh John Myczek? Ini mencari hierarki dari kontrol yang diberikan untuk menemukan kontrol leluhur dari jenis tertentu.
Sebut saja seperti ini untuk menemukan
Window
kontrol yang disebutExampleTextBox
:sumber
Inilah kode saya untuk menemukan kontrol berdasarkan Jenis sambil mengontrol seberapa dalam kita masuk ke hierarki (maxDepth == 0 berarti jauh lebih dalam).
sumber
exciton80 ... Saya mengalami masalah dengan kode Anda tidak berulang melalui usercontrols. Itu mengenai root Grid dan melempar kesalahan. Saya percaya ini memperbaikinya untuk saya:
sumber
Saya memiliki fungsi urutan seperti ini (yang sepenuhnya umum):
Mendapatkan anak langsung:
Menemukan semua anak di bawah pohon hiararkis:
Anda dapat memanggil ini di Window untuk mendapatkan semua kontrol.
Setelah Anda memiliki koleksi, Anda dapat menggunakan LINQ (yaitu OfType, Di mana).
sumber
Karena pertanyaannya cukup umum sehingga mungkin menarik orang mencari jawaban untuk kasus-kasus yang sangat sepele: jika Anda hanya ingin anak daripada keturunan, Anda dapat menggunakan Linq:
atau tentu saja jelas untuk loop berulang atas Anak.
sumber
Opsi ini sudah berbicara tentang melintasi Pohon Visual di C #. Mungkin untuk melintasi pohon visual dalam xaml juga menggunakan ekstensi markup RelativeSource. msdn
temukan berdasarkan tipe
sumber
Berikut ini solusi yang menggunakan predikat fleksibel:
Misalnya Anda bisa menyebutnya seperti ini:
sumber
Kode ini hanya memperbaiki bug jawaban @CrimsonX:
Anda hanya perlu terus memanggil metode secara rekursif jika jenisnya cocok tetapi nama tidak (ini terjadi ketika Anda lulus
FrameworkElement
sebagaiT
). kalau tidak itu akan kembalinull
dan itu salah.sumber
Untuk menemukan leluhur tipe tertentu dari kode, Anda dapat menggunakan:
Implementasi ini menggunakan iterasi alih-alih rekursi yang bisa sedikit lebih cepat.
Jika Anda menggunakan C # 7, ini bisa dibuat sedikit lebih pendek:
sumber
Coba ini
Kode di Balik
sumber