Bagikan melalui


Tata letak

Topik ini menjelaskan sistem tata letak Windows Presentation Foundation (WPF). Memahami bagaimana dan kapan perhitungan tata letak terjadi sangat penting untuk membuat antarmuka pengguna di WPF.

Topik ini berisi bagian berikut:

Kotak Pembatas Elemen

Ketika memikirkan tata letak di WPF, penting untuk memahami kotak pembatas yang mengelilingi semua elemen. Setiap FrameworkElement yang digunakan oleh sistem tata letak dapat dianggap sebagai persegi panjang yang di-slot ke dalam tata letak. Kelas LayoutInformation mengembalikan batas alokasi tata letak elemen, atau slot. Ukuran persegi ditentukan dengan menghitung ruang layar yang tersedia, ukuran batasan apa pun, properti khusus tata letak (seperti margin dan padding), dan perilaku individu dari elemen induk Panel . Memproses data ini, sistem tata letak dapat menghitung posisi semua anak tertentu Panel. Penting untuk diingat bahwa karakteristik ukuran yang ditentukan pada elemen induk, seperti Border, mempengaruhi anak-anaknya.

Ilustrasi berikut menunjukkan tata letak sederhana.

Screenshot that shows a typical grid, no bounding box superimposed.

Tata letak ini dapat dicapai dengan menggunakan XAML berikut.

<Grid Name="myGrid" Background="LightSteelBlue" Height="150">
  <Grid.ColumnDefinitions>
    <ColumnDefinition Width="250"/>
  </Grid.ColumnDefinitions>
  <Grid.RowDefinitions>
    <RowDefinition />
    <RowDefinition />
    <RowDefinition />
  </Grid.RowDefinitions>
  <TextBlock Name="txt1" Margin="5" FontSize="16" FontFamily="Verdana" Grid.Column="0" Grid.Row="0">Hello World!</TextBlock>
  <Button Click="getLayoutSlot1" Width="125" Height="25" Grid.Column="0" Grid.Row="1">Show Bounding Box</Button>
  <TextBlock Name="txt2" Grid.Column="1" Grid.Row="2"/>
</Grid>

Elemen tunggal TextBlock dihosting dalam Grid. Meskipun teks hanya mengisi sudut kiri atas kolom pertama, ruang yang TextBlock dialokasikan untuk sebenarnya jauh lebih besar. Kotak pembatas apa pun FrameworkElement dapat diambil dengan menggunakan GetLayoutSlot metode . Ilustrasi berikut menunjukkan kotak pembatas untuk elemen .TextBlock

Screenshot that shows that the TextBlock bounding box is now visible.

Seperti yang ditunjukkan oleh persegi panjang kuning, ruang yang dialokasikan untuk TextBlock elemen sebenarnya jauh lebih besar dari yang muncul. Karena elemen tambahan ditambahkan ke Grid, alokasi ini dapat menyusut atau diperluas, tergantung pada jenis dan ukuran elemen yang ditambahkan.

Slot tata letak diterjemahkan TextBlock ke dalam Path dengan menggunakan GetLayoutSlot metode . Teknik ini dapat berguna untuk menampilkan kotak pembatas elemen.

private void getLayoutSlot1(object sender, System.Windows.RoutedEventArgs e)
{
    RectangleGeometry myRectangleGeometry = new RectangleGeometry();
    myRectangleGeometry.Rect = LayoutInformation.GetLayoutSlot(txt1);
    Path myPath = new Path();
    myPath.Data = myRectangleGeometry;
    myPath.Stroke = Brushes.LightGoldenrodYellow;
    myPath.StrokeThickness = 5;
    Grid.SetColumn(myPath, 0);
    Grid.SetRow(myPath, 0);
    myGrid.Children.Add(myPath);
    txt2.Text = "LayoutSlot is equal to " + LayoutInformation.GetLayoutSlot(txt1).ToString();
}
Private Sub getLayoutSlot1(ByVal sender As Object, ByVal e As RoutedEventArgs)
    Dim myRectangleGeometry As New RectangleGeometry
    myRectangleGeometry.Rect = LayoutInformation.GetLayoutSlot(txt1)
    Dim myPath As New Path
    myPath.Data = myRectangleGeometry
    myPath.Stroke = Brushes.LightGoldenrodYellow
    myPath.StrokeThickness = 5
    Grid.SetColumn(myPath, 0)
    Grid.SetRow(myPath, 0)
    myGrid.Children.Add(myPath)
    txt2.Text = "LayoutSlot is equal to " + LayoutInformation.GetLayoutSlot(txt1).ToString()
End Sub

Sistem Tata Letak

Paling sederhana, tata letak adalah sistem rekursif yang mengarah ke elemen yang berukuran, diposisikan, dan digambar. Lebih khusus lagi, tata letak menjelaskan proses mengukur dan mengatur anggota Panel koleksi elemen Children . Tata letak adalah proses intensif. Semakin besar Children koleksi, semakin besar jumlah perhitungan yang harus dibuat. Kompleksitas juga dapat diperkenalkan berdasarkan perilaku tata letak yang ditentukan oleh Panel elemen yang memiliki koleksi. Yang relatif sederhana Panel, seperti Canvas, dapat memiliki performa yang jauh lebih baik daripada yang lebih kompleks Panel, seperti Grid.

Setiap kali anak mengubah posisinya, anak UIElement berpotensi memicu pass baru oleh sistem tata letak. Oleh karena itu, penting untuk memahami peristiwa yang dapat memanggil sistem tata letak, karena pemanggilan yang tidak perlu dapat menyebabkan performa aplikasi yang buruk. Berikut ini menjelaskan proses yang terjadi ketika sistem tata letak dipanggil.

  1. UIElement Anak memulai proses tata letak dengan terlebih dahulu mengukur properti intinya.

  2. Properti ukuran yang ditentukan pada FrameworkElement dievaluasi, seperti Width, , Heightdan Margin.

  3. Panel-logika spesifik diterapkan, seperti Dock arah atau tumpukan Orientation.

  4. Konten diatur setelah semua anak diukur.

  5. Koleksi Children digambar di layar.

  6. Proses ini dipanggil lagi jika tambahan Children ditambahkan ke koleksi, diterapkan LayoutTransform , atau metode dipanggil UpdateLayout .

Proses ini dan bagaimana pemanggilannya didefinisikan secara lebih rinci di bagian berikut.

Mengukur dan Mengatur Anak

Sistem tata letak menyelesaikan dua pass untuk setiap anggota Children koleksi, pass pengukuran, dan pass pengaturan. Setiap anak Panel menyediakan metode dan ArrangeOverride sendiri MeasureOverride untuk mencapai perilaku tata letak spesifiknya sendiri.

Selama lulus pengukuran, setiap anggota Children koleksi dievaluasi. Proses dimulai dengan panggilan ke Measure metode . Metode ini dipanggil dalam implementasi elemen induk Panel , dan tidak harus dipanggil secara eksplisit agar tata letak terjadi.

Pertama, properti UIElement ukuran asli dievaluasi, seperti Clip dan Visibility. Ini menghasilkan nilai bernama constraintSize yang diteruskan ke MeasureCore.

Kedua, properti kerangka kerja yang ditentukan diproses FrameworkElement , yang memengaruhi nilai constraintSize. Properti ini umumnya menjelaskan karakteristik ukuran dari yang mendasar , seperti Height, , MarginWidth, dan Style.UIElement Masing-masing properti ini dapat mengubah ruang yang diperlukan untuk menampilkan elemen . MeasureOverride kemudian dipanggil dengan constraintSize sebagai parameter.

Catatan

Ada perbedaan antara properti dan Height dan Width dan ActualHeightActualWidth. Misalnya, ActualHeight properti adalah nilai terhitung berdasarkan input tinggi lainnya dan sistem tata letak. Nilai diatur oleh sistem tata letak itu sendiri, berdasarkan pass penyajian aktual, dan karenanya dapat sedikit tertinggal di belakang nilai properti yang ditetapkan, seperti Height, yang merupakan dasar dari perubahan input.

Karena ActualHeight merupakan nilai terhitung, Anda harus menyadari bahwa mungkin ada beberapa perubahan yang dilaporkan secara bertahap atau bertahap sebagai akibat dari berbagai operasi oleh sistem tata letak. Sistem tata letak mungkin menghitung ruang pengukuran yang diperlukan untuk elemen anak, batasan oleh elemen induk, dan sebagainya.

Tujuan utama dari pass pengukuran adalah agar anak menentukan , DesiredSizeyang terjadi selama MeasureCore panggilan. Nilai DesiredSize disimpan oleh Measure untuk digunakan selama pass pengaturan konten.

Pass pengaturan dimulai dengan panggilan ke Arrange metode . Selama kode susun, elemen induk Panel menghasilkan persegi panjang yang mewakili batas anak. Nilai ini diteruskan ke ArrangeCore metode untuk diproses.

Metode mengevaluasi ArrangeCoreDesiredSize anak dan mengevaluasi margin tambahan yang dapat memengaruhi ukuran elemen yang dirender. ArrangeCorearrangeSizemenghasilkan , yang diteruskan ke ArrangeOverride metode Panel sebagai parameter. ArrangeOverridefinalSize menghasilkan anak. Terakhir, metode ini ArrangeCore melakukan evaluasi akhir properti offset, seperti margin dan perataan, dan menempatkan anak dalam slot tata letaknya. Anak tidak harus (dan sering tidak) mengisi seluruh ruang yang dialokasikan. Kontrol kemudian dikembalikan ke induk Panel dan proses tata letak selesai.

Elemen Panel dan Perilaku Tata Letak Kustom

WPF mencakup sekelompok elemen yang berasal dari Panel. Elemen-elemen ini Panel memungkinkan banyak tata letak yang kompleks. Misalnya, elemen tumpukan dapat dengan mudah dicapai dengan menggunakan StackPanel elemen , sementara tata letak yang mengalir lebih kompleks dan bebas dimungkinkan dengan menggunakan Canvas.

Tabel berikut ini meringkas elemen tata letak Panel yang tersedia.

Nama panel Deskripsi
Canvas Menentukan area di mana Anda dapat secara eksplisit memposisikan elemen turunan dengan koordinat relatif terhadap area tersebut Canvas .
DockPanel Menentukan area di mana Anda dapat mengatur elemen turunan baik secara horizontal atau vertikal, relatif satu sama lain.
Grid Menentukan area kisi fleksibel yang terdiri dari kolom dan baris.
StackPanel Mengatur elemen turunan ke dalam satu baris yang dapat berorientasi secara horizontal atau vertikal.
VirtualizingPanel Menyediakan kerangka kerja untuk Panel elemen yang memvirtualisasi pengumpulan data anak mereka. Ini adalah kelas abstrak.
WrapPanel Memposisikan elemen turunan dalam posisi berurutan dari kiri ke kanan, memecah konten ke baris berikutnya di tepi kotak yang berisi. Pengurutan berikutnya terjadi secara berurutan dari atas ke bawah atau kanan ke kiri, tergantung pada nilai Orientation properti.

Untuk aplikasi yang memerlukan tata letak yang tidak dimungkinkan dengan menggunakan salah satu elemen yang telah Panel ditentukan sebelumnya, perilaku tata letak kustom dapat dicapai dengan mewarisi dari Panel dan mengambil alih MeasureOverride metode dan ArrangeOverride .

Pertimbangan Performa Tata Letak

Tata letak adalah proses rekursif. Setiap elemen anak dalam koleksi akan diproses Children selama setiap pemanggilan sistem tata letak. Akibatnya, memicu sistem tata letak harus dihindari ketika tidak diperlukan. Pertimbangan berikut dapat membantu Anda mencapai performa yang lebih baik.

  • Ketahui perubahan nilai properti mana yang akan memaksa pembaruan rekursif oleh sistem tata letak.

    Properti dependensi yang nilainya dapat menyebabkan sistem tata letak diinisialisasi ditandai dengan bendera publik. AffectsMeasure dan AffectsArrange memberikan petunjuk yang berguna tentang perubahan nilai properti mana yang akan memaksa pembaruan rekursif oleh sistem tata letak. Secara umum, properti apa pun yang dapat memengaruhi ukuran kotak pembatas elemen harus memiliki bendera yang AffectsMeasure diatur ke true. Untuk informasi selengkapnya, lihat Gambaran Umum Properti Dependensi.

  • Jika memungkinkan, gunakan RenderTransform alih-alih LayoutTransform.

    LayoutTransform Bisa menjadi cara yang sangat berguna untuk memengaruhi konten antarmuka pengguna (UI). Namun, jika efek transformasi tidak harus berdampak pada posisi elemen lain, yang terbaik adalah menggunakan RenderTransform sebagai gantinya, karena RenderTransform tidak memanggil sistem tata letak. LayoutTransform menerapkan transformasinya dan memaksa pembaruan tata letak rekursif untuk memperhitungkan posisi baru elemen yang terpengaruh.

  • Hindari panggilan yang tidak perlu ke UpdateLayout.

    Metode ini UpdateLayout memaksa pembaruan tata letak rekursif, dan sering kali tidak diperlukan. Kecuali Anda yakin bahwa pembaruan penuh diperlukan, bergantung pada sistem tata letak untuk memanggil metode ini untuk Anda.

  • Saat bekerja dengan koleksi besar Children , pertimbangkan untuk menggunakan VirtualizingStackPanel alih-alih reguler StackPanel.

    Dengan memvirtualisasi koleksi anak, satu-satunya VirtualizingStackPanel menyimpan objek dalam memori yang saat ini berada dalam ViewPort induk. Akibatnya, performa meningkat secara substansial dalam sebagian besar skenario.

Perenderan Sub-piksel dan Pembulatan Tata Letak

Sistem grafis WPF menggunakan unit independen perangkat untuk memungkinkan resolusi dan kemandirian perangkat. Setiap piksel independen perangkat secara otomatis diskalakan dengan pengaturan titik per inci (dpi) sistem. Ini menyediakan penskalaan yang tepat untuk aplikasi WPF untuk pengaturan dpi yang berbeda dan membuat aplikasi secara otomatis sadar dpi.

Namun, kemandirian dpi ini dapat menciptakan penyajian tepi yang tidak teratur karena anti-aliasing. Artefak ini, biasanya terlihat sebagai tepi buram atau semi transparan, dapat terjadi ketika lokasi tepi jatuh di tengah piksel perangkat alih-alih antar piksel perangkat. Sistem tata letak menyediakan cara untuk menyesuaikan ini dengan pembulatan tata letak. Pembulatan tata letak adalah tempat sistem tata letak membulatkan nilai piksel non-integral selama kode tata letak.

Pembulatan tata letak dinonaktifkan secara default. Untuk mengaktifkan pembulatan tata letak, atur properti ke UseLayoutRoundingtrue pada apa pun FrameworkElement. Karena ini adalah properti dependensi, nilai akan disebarluaskan ke semua anak di pohon visual. Untuk mengaktifkan pembulatan tata letak untuk seluruh UI, atur UseLayoutRounding ke true pada kontainer akar. Misalnya, lihat UseLayoutRounding.

Apa Berikutnya

Memahami bagaimana elemen diukur dan disusun adalah langkah pertama dalam memahami tata letak. Untuk informasi selengkapnya tentang elemen yang tersedia Panel , lihat Gambaran Umum Panel. Untuk lebih memahami berbagai properti pemosisian yang dapat memengaruhi tata letak, lihat Gambaran Umum Perataan, Margin, dan Padding. Ketika Anda siap untuk menyatukan semuanya dalam aplikasi ringan, lihat Walkthrough: Aplikasi desktop WPF pertama saya.

Baca juga