Melakukan Pengujian di Lapisan Visual
Topik ini memberikan gambaran umum tentang fungsionalitas pengujian hit yang disediakan oleh lapisan visual. Dukungan pengujian hit memungkinkan Anda menentukan apakah geometri atau nilai titik termasuk dalam konten yang Visualdirender dari , memungkinkan Anda menerapkan perilaku antarmuka pengguna seperti persegi panjang pilihan untuk memilih beberapa objek.
Skenario Pengujian Hit
Kelas UIElement ini menyediakan InputHitTest metode , yang memungkinkan Anda untuk menekan pengujian terhadap elemen menggunakan nilai koordinat tertentu. Dalam banyak kasus, metode ini InputHitTest menyediakan fungsionalitas yang diinginkan untuk menerapkan pengujian elemen hit. Namun, ada beberapa skenario di mana Anda mungkin perlu menerapkan pengujian hit di lapisan visual.
Uji terhadap non-objekUIElement : Ini berlaku jika Anda menekan pengujian non-objekUIElement , seperti DrawingVisual atau objek grafis.
Pengujian tekan menggunakan geometri: Ini berlaku jika Anda perlu menekan pengujian menggunakan objek geometri daripada nilai koordinat titik.
Uji terhadap beberapa objek: Ini berlaku saat Anda perlu menekan pengujian terhadap beberapa objek, seperti objek yang tumpang tindih. Anda bisa mendapatkan hasil untuk semua visual yang beririsan geometri atau titik, bukan hanya yang pertama.
Mengabaikan UIElement kebijakan pengujian hit: Ini berlaku ketika Anda perlu mengabaikan UIElement kebijakan pengujian hit, yang mempertimbangkan faktor-faktor seperti apakah elemen dinonaktifkan atau tidak terlihat.
Catatan
Untuk sampel kode lengkap yang mengilustrasikan pengujian hit di lapisan visual, lihat Uji Hit Menggunakan Sampel DrawingVisuals dan Uji Hit dengan Sampel Interoperasi Win32.
Tekan Dukungan Pengujian
Tujuan metode HitTest di VisualTreeHelper kelas adalah untuk menentukan apakah geometri atau nilai koordinat titik berada dalam konten yang dirender dari objek tertentu, seperti kontrol atau elemen grafis. Misalnya, Anda dapat menggunakan pengujian hit untuk menentukan apakah klik mouse dalam persegi panjang pembatas objek berada dalam geometri lingkaran. Anda juga dapat memilih untuk mengambil alih implementasi default pengujian hit untuk melakukan perhitungan pengujian hit kustom Anda sendiri.
Ilustrasi berikut menunjukkan hubungan antara wilayah objek non-persegi panjang dan persegi panjang pembatasnya.
Diagram wilayah uji hit yang valid
Tekan Pengujian dan Z-Order
Lapisan visual Windows Presentation Foundation (WPF) mendukung pengujian hit terhadap semua objek di bawah titik atau geometri, bukan hanya objek paling atas. Hasil dikembalikan dalam urutan z. Namun, objek visual yang Anda berikan sebagai parameter ke HitTest metode menentukan bagian mana dari pohon visual yang akan ditemui pengujian. Anda dapat menekan pengujian terhadap seluruh pohon visual, atau bagian mana pun darinya.
Dalam ilustrasi berikut, objek lingkaran berada di atas objek persegi dan segitiga. Jika Anda hanya tertarik untuk menguji objek visual yang nilai z-order-nya paling atas, Anda dapat mengatur enumerasi pengujian hit visual untuk kembali Stop dari HitTestResultCallback untuk menghentikan traversal pengujian hit setelah item pertama.
Diagram urutan z pohon visual
Jika Anda ingin menghitung semua objek visual di bawah titik atau geometri tertentu, kembalikan ContinueHitTestResultCallbackdari . Ini berarti Anda dapat menekan pengujian untuk objek visual yang berada di bawah objek lain, bahkan jika mereka sepenuhnya dikaburkan. Lihat kode sampel di bagian "Menggunakan Hit Test Results Callback" untuk informasi selengkapnya.
Catatan
Objek visual yang transparan juga dapat ditemui tes.
Menggunakan Pengujian Hit Default
Anda dapat mengidentifikasi apakah titik berada dalam geometri objek visual, dengan menggunakan HitTest metode untuk menentukan objek visual dan nilai koordinat titik untuk diuji. Parameter objek visual mengidentifikasi titik awal di pohon visual untuk pencarian pengujian hit. Jika objek visual ditemukan di pohon visual yang geometrinya berisi koordinat, objek tersebut diatur ke VisualHit properti HitTestResult objek. HitTestResult kemudian dikembalikan dari HitTest metode . Jika titik tidak terkandung dengan sub-pohon visual yang Anda tekan pengujian, HitTest mengembalikan null
.
Catatan
Pengujian hit default selalu mengembalikan objek paling atas dalam urutan z. Untuk mengidentifikasi semua objek visual, bahkan objek yang mungkin sebagian atau sepenuhnya dikaburkan, gunakan panggilan balik hasil pengujian hit.
Nilai koordinat yang Anda berikan sebagai parameter titik untuk HitTest metode harus relatif terhadap ruang koordinat objek visual yang Anda tekan pengujiannya. Misalnya, jika Anda memiliki objek visual berlapis yang ditentukan pada (100, 100) di ruang koordinat induk, maka tekan pengujian visual anak pada (0, 0) setara dengan pengujian pada (100, 100) di ruang koordinat induk.
Kode berikut menunjukkan cara menyiapkan penanganan aktivitas mouse untuk UIElement objek yang digunakan untuk mengambil peristiwa yang digunakan untuk pengujian temuan.
// Respond to the left mouse button down event by initiating the hit test.
private void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
// Retrieve the coordinate of the mouse position.
Point pt = e.GetPosition((UIElement)sender);
// Perform the hit test against a given portion of the visual object tree.
HitTestResult result = VisualTreeHelper.HitTest(myCanvas, pt);
if (result != null)
{
// Perform action on hit visual object.
}
}
' Respond to the left mouse button down event by initiating the hit test.
Private Overloads Sub OnMouseLeftButtonDown(ByVal sender As Object, ByVal e As MouseButtonEventArgs)
' Retrieve the coordinate of the mouse position.
Dim pt As Point = e.GetPosition(CType(sender, UIElement))
' Perform the hit test against a given portion of the visual object tree.
Dim result As HitTestResult = VisualTreeHelper.HitTest(myCanvas, pt)
If result IsNot Nothing Then
' Perform action on hit visual object.
End If
End Sub
Bagaimana Visual Tree Mempengaruhi Pengujian Hit
Titik awal di pohon visual menentukan objek mana yang dikembalikan selama enumerasi pengujian hit objek. Jika Anda memiliki beberapa objek yang ingin Anda tekan uji, objek visual yang digunakan sebagai titik awal di pohon visual harus menjadi leluhur umum dari semua objek yang menarik. Misalnya, jika Anda tertarik untuk menguji elemen tombol dan visual gambar dalam diagram berikut, Anda harus mengatur titik awal di pohon visual ke leluhur umum keduanya. Dalam hal ini, elemen kanvas adalah nenek moyang umum dari elemen tombol dan visual gambar.
Diagram hierarki pohon visual
Catatan
Properti IsHitTestVisible mendapatkan atau menetapkan nilai yang menyatakan apakah UIElementobjek -turunan mungkin dapat dikembalikan sebagai hasil pengujian hit dari beberapa bagian konten yang dirender. Ini memungkinkan Anda untuk secara selektif mengubah pohon visual untuk menentukan objek visual mana yang terlibat dalam pengujian hit.
Menggunakan Hit Test Result Callback
Anda dapat menghitung semua objek visual di pohon visual yang geometrinya berisi nilai koordinat tertentu. Ini memungkinkan Anda mengidentifikasi semua objek visual, bahkan objek yang mungkin sebagian atau sepenuhnya dikaburkan oleh objek visual lainnya. Untuk menghitung objek visual di pohon visual, gunakan HitTest metode dengan fungsi panggilan balik uji hit. Fungsi panggilan balik uji hit dipanggil oleh sistem ketika nilai koordinat yang Anda tentukan terkandung dalam objek visual.
Selama enumerasi hasil pengujian hit, Anda tidak boleh melakukan operasi apa pun yang memodifikasi pohon visual. Menambahkan atau menghapus objek dari pohon visual saat sedang dilalui dapat mengakibatkan perilaku yang tidak dapat diprediksi. Anda dapat memodifikasi pohon visual dengan aman setelah HitTest metode kembali. Anda mungkin ingin menyediakan struktur data, seperti ArrayList, untuk menyimpan nilai selama enumerasi hasil pengujian hit.
// Respond to the right mouse button down event by setting up a hit test results callback.
private void OnMouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
// Retrieve the coordinate of the mouse position.
Point pt = e.GetPosition((UIElement)sender);
// Clear the contents of the list used for hit test results.
hitResultsList.Clear();
// Set up a callback to receive the hit test result enumeration.
VisualTreeHelper.HitTest(myCanvas, null,
new HitTestResultCallback(MyHitTestResult),
new PointHitTestParameters(pt));
// Perform actions on the hit test results list.
if (hitResultsList.Count > 0)
{
Console.WriteLine("Number of Visuals Hit: " + hitResultsList.Count);
}
}
' Respond to the right mouse button down event by setting up a hit test results callback.
Private Overloads Sub OnMouseRightButtonDown(ByVal sender As Object, ByVal e As MouseButtonEventArgs)
' Retrieve the coordinate of the mouse position.
Dim pt As Point = e.GetPosition(CType(sender, UIElement))
' Clear the contents of the list used for hit test results.
hitResultsList.Clear()
' Set up a callback to receive the hit test result enumeration.
VisualTreeHelper.HitTest(myCanvas, Nothing, New HitTestResultCallback(AddressOf MyHitTestResult), New PointHitTestParameters(pt))
' Perform actions on the hit test results list.
If hitResultsList.Count > 0 Then
Console.WriteLine("Number of Visuals Hit: " & hitResultsList.Count)
End If
End Sub
Metode panggilan balik uji hit mendefinisikan tindakan yang Anda lakukan saat pengujian hit diidentifikasi pada objek visual tertentu di pohon visual. Setelah melakukan tindakan, Anda mengembalikan HitTestResultBehavior nilai yang menentukan apakah akan melanjutkan enumerasi objek visual lainnya atau tidak.
// Return the result of the hit test to the callback.
public HitTestResultBehavior MyHitTestResult(HitTestResult result)
{
// Add the hit test result to the list that will be processed after the enumeration.
hitResultsList.Add(result.VisualHit);
// Set the behavior to return visuals at all z-order levels.
return HitTestResultBehavior.Continue;
}
' Return the result of the hit test to the callback.
Public Function MyHitTestResult(ByVal result As HitTestResult) As HitTestResultBehavior
' Add the hit test result to the list that will be processed after the enumeration.
hitResultsList.Add(result.VisualHit)
' Set the behavior to return visuals at all z-order levels.
Return HitTestResultBehavior.Continue
End Function
Catatan
Urutan enumerasi objek visual hit adalah dengan z-order. Objek visual pada tingkat z-order paling atas adalah objek pertama yang dijumlahkan. Objek visual lain yang dijumlahkan berada pada tingkat z-order yang menurun. Urutan enumerasi ini sesuai dengan urutan penyajian visual.
Anda dapat menghentikan enumerasi objek visual kapan saja dalam fungsi panggilan balik uji hit dengan mengembalikan Stop.
// Set the behavior to stop enumerating visuals.
return HitTestResultBehavior.Stop;
' Set the behavior to stop enumerating visuals.
Return HitTestResultBehavior.Stop
Menggunakan Panggilan Balik Filter Uji Tekan
Anda dapat menggunakan filter uji tekan opsional untuk membatasi objek yang diteruskan ke hasil pengujian hit. Ini memungkinkan Anda untuk mengabaikan bagian pohon visual yang tidak tertarik untuk diproses dalam hasil pengujian hit Anda. Untuk menerapkan filter uji hit, Anda menentukan fungsi panggilan balik filter uji hit dan meneruskannya sebagai nilai parameter saat Anda memanggil HitTest metode .
// Respond to the mouse wheel event by setting up a hit test filter and results enumeration.
private void OnMouseWheel(object sender, MouseWheelEventArgs e)
{
// Retrieve the coordinate of the mouse position.
Point pt = e.GetPosition((UIElement)sender);
// Clear the contents of the list used for hit test results.
hitResultsList.Clear();
// Set up a callback to receive the hit test result enumeration.
VisualTreeHelper.HitTest(myCanvas,
new HitTestFilterCallback(MyHitTestFilter),
new HitTestResultCallback(MyHitTestResult),
new PointHitTestParameters(pt));
// Perform actions on the hit test results list.
if (hitResultsList.Count > 0)
{
ProcessHitTestResultsList();
}
}
' Respond to the mouse wheel event by setting up a hit test filter and results enumeration.
Private Overloads Sub OnMouseWheel(ByVal sender As Object, ByVal e As MouseWheelEventArgs)
' Retrieve the coordinate of the mouse position.
Dim pt As Point = e.GetPosition(CType(sender, UIElement))
' Clear the contents of the list used for hit test results.
hitResultsList.Clear()
' Set up a callback to receive the hit test result enumeration.
VisualTreeHelper.HitTest(myCanvas, New HitTestFilterCallback(AddressOf MyHitTestFilter), New HitTestResultCallback(AddressOf MyHitTestResult), New PointHitTestParameters(pt))
' Perform actions on the hit test results list.
If hitResultsList.Count > 0 Then
ProcessHitTestResultsList()
End If
End Sub
Jika Anda tidak ingin menyediakan fungsi panggilan balik filter uji tekan opsional, berikan null
nilai sebagai parameternya untuk metode tersebut HitTest .
// Set up a callback to receive the hit test result enumeration,
// but no hit test filter enumeration.
VisualTreeHelper.HitTest(myCanvas,
null, // No hit test filtering.
new HitTestResultCallback(MyHitTestResult),
new PointHitTestParameters(pt));
' Set up a callback to receive the hit test result enumeration,
' but no hit test filter enumeration.
VisualTreeHelper.HitTest(myCanvas, Nothing, New HitTestResultCallback(AddressOf MyHitTestResult), New PointHitTestParameters(pt)) ' No hit test filtering.
Memangkas pohon visual
Fungsi panggilan balik filter uji tekan memungkinkan Anda menghitung semua visual yang konten yang dirender berisi koordinat yang Anda tentukan. Namun, Anda mungkin ingin mengabaikan cabang pohon visual tertentu yang tidak tertarik untuk diproses dalam fungsi panggilan balik hasil pengujian hit Anda. Nilai pengembalian fungsi panggilan balik filter uji hit menentukan jenis tindakan apa yang harus diambil enumerasi objek visual. Misalnya, jika Anda mengembalikan nilai , ContinueSkipSelfAndChildren, Anda dapat menghapus objek visual saat ini dan turunannya dari enumerasi hasil pengujian hit. Ini berarti bahwa fungsi panggilan balik hasil pengujian hit tidak akan melihat objek ini dalam enumerasinya. Pemangkasan pohon visual objek mengurangi jumlah pemrosesan selama lulus enumerasi hasil pengujian hit. Dalam contoh kode berikut, filter melompati label dan turunannya dan menekan pengujian yang lain.
// Filter the hit test values for each object in the enumeration.
public HitTestFilterBehavior MyHitTestFilter(DependencyObject o)
{
// Test for the object value you want to filter.
if (o.GetType() == typeof(Label))
{
// Visual object and descendants are NOT part of hit test results enumeration.
return HitTestFilterBehavior.ContinueSkipSelfAndChildren;
}
else
{
// Visual object is part of hit test results enumeration.
return HitTestFilterBehavior.Continue;
}
}
' Filter the hit test values for each object in the enumeration.
Public Function MyHitTestFilter(ByVal o As DependencyObject) As HitTestFilterBehavior
' Test for the object value you want to filter.
If o.GetType() Is GetType(Label) Then
' Visual object and descendants are NOT part of hit test results enumeration.
Return HitTestFilterBehavior.ContinueSkipSelfAndChildren
Else
' Visual object is part of hit test results enumeration.
Return HitTestFilterBehavior.Continue
End If
End Function
Catatan
Panggilan balik filter uji tekan terkadang akan dipanggil jika panggilan balik hasil pengujian tes tidak dipanggil.
Mengesampingkan Pengujian Hit Default
Anda dapat mengambil alih dukungan pengujian hit default objek visual dengan mengambil alih HitTestCore metode . Ini berarti bahwa ketika Anda memanggil HitTest metode , implementasi penggantian HitTestCore Anda dipanggil. Metode penimpaan Anda dipanggil ketika tes hit berada dalam persegi panjang pembatas objek visual, bahkan jika koordinat berada di luar konten objek visual yang dirender.
// Override default hit test support in visual object.
protected override HitTestResult HitTestCore(PointHitTestParameters hitTestParameters)
{
Point pt = hitTestParameters.HitPoint;
// Perform custom actions during the hit test processing,
// which may include verifying that the point actually
// falls within the rendered content of the visual.
// Return hit on bounding rectangle of visual object.
return new PointHitTestResult(this, pt);
}
' Override default hit test support in visual object.
Protected Overrides Overloads Function HitTestCore(ByVal hitTestParameters As PointHitTestParameters) As HitTestResult
Dim pt As Point = hitTestParameters.HitPoint
' Perform custom actions during the hit test processing,
' which may include verifying that the point actually
' falls within the rendered content of the visual.
' Return hit on bounding rectangle of visual object.
Return New PointHitTestResult(Me, pt)
End Function
Mungkin ada kalanya Anda ingin menekan pengujian terhadap persegi panjang pembatas dan konten objek visual yang dirender. Dengan menggunakan PointHitTestParameters
nilai parameter dalam metode yang ditimpa HitTestCore sebagai parameter ke metode HitTestCoredasar , Anda dapat melakukan tindakan berdasarkan hit persegi panjang pembatas objek visual, lalu melakukan pengujian hit kedua terhadap konten objek visual yang dirender.
// Override default hit test support in visual object.
protected override HitTestResult HitTestCore(PointHitTestParameters hitTestParameters)
{
// Perform actions based on hit test of bounding rectangle.
// ...
// Return results of base class hit testing,
// which only returns hit on the geometry of visual objects.
return base.HitTestCore(hitTestParameters);
}
' Override default hit test support in visual object.
Protected Overrides Overloads Function HitTestCore(ByVal hitTestParameters As PointHitTestParameters) As HitTestResult
' Perform actions based on hit test of bounding rectangle.
' ...
' Return results of base class hit testing,
' which only returns hit on the geometry of visual objects.
Return MyBase.HitTestCore(hitTestParameters)
End Function
Baca juga
.NET Desktop feedback