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 diibaratkan sebagai persegi panjang yang ditempatkan 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 Panel induk. Dalam memproses data ini, sistem tata letak dapat menghitung posisi semua turunan dari suatu elemen Paneltertentu. Penting untuk diingat bahwa karakteristik ukuran yang didefinisikan pada elemen induk, seperti Border, mempengaruhi anak-anaknya.

Ilustrasi berikut menunjukkan tata letak sederhana.

Cuplikan layar yang memperlihatkan kisi yang khas, tidak ada kotak pembatas yang ditumpangkan.

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 TextBlock tunggal berada di dalam Grid. Meskipun teks hanya mengisi sudut kiri atas kolom pertama, ruang yang dialokasikan untuk TextBlock sebenarnya jauh lebih besar. Kotak pembatas dari setiap FrameworkElement dapat diperoleh dengan menggunakan metode GetLayoutSlot. Ilustrasi berikut menunjukkan kotak pembatas untuk elemen TextBlock.

Cuplikan layar yang memperlihatkan bahwa kotak pembatas TextBlock sekarang terlihat.

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

Slot tata letak TextBlock diterjemahkan ke dalam Path dengan menggunakan metode GetLayoutSlot. 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

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

Setiap kali anak UIElement mengubah posisinya, anak tersebut berpotensi memicu pemrosesan ulang 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. Anak UIElement memulai proses tata letak dengan terlebih dahulu mengukur properti utamanya.

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

  3. Panel-logika khusus diterapkan, seperti arah Dock atau menumpuk Orientation.

  4. Konten diatur setelah semua anak diukur.

  5. Koleksi Children digambar di layar.

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

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

Mengukur dan Mengatur Anak

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

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

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

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

Nota

Ada perbedaan antara properti Height dan Width dan ActualHeight dan ActualWidth. Misalnya, properti ActualHeight adalah nilai terhitung berdasarkan input tinggi dan sistem tata letak lainnya. Nilai diatur oleh sistem tata letak itu sendiri, berdasarkan proses rendering aktual, dan karenanya mungkin sedikit terlambat dibandingkan dengan nilai properti yang ditetapkan, seperti Height, yang menjadi dasar perubahan pada input.

Karena ActualHeight adalah nilai yang dihitung, Anda harus menyadari bahwa mungkin ada berbagai perubahan yang dilaporkan secara bertahap 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 DesiredSize, yang terjadi selama panggilan MeasureCore. Nilai DesiredSize disimpan oleh Measure untuk digunakan selama proses pengaturan konten.

Pengaturan pass dimulai dengan memanggil metode Arrange. Selama proses pengaturan, elemen induk Panel menghasilkan persegi panjang yang mewakili batas dari elemen anak. Nilai ini diteruskan ke metode ArrangeCore untuk diproses.

Metode ArrangeCore mengevaluasi faktor DesiredSize dari anak dan juga mengevaluasi margin tambahan yang mungkin memengaruhi ukuran elemen yang dihasilkan. ArrangeCore menghasilkan arrangeSize, yang diteruskan sebagai parameter ke metode ArrangeOverride dari Panel. ArrangeOverride menghasilkan finalSize si anak. Akhirnya, metode 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 Panel induk dan proses tata letak selesai.

Elemen Panel dan Perilaku Tata Letak Kustom

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

Tabel berikut meringkas elemen tata letak Panel yang tersedia.

Nama panel Deskripsi
Canvas Menentukan area di mana Anda dapat secara eksplisit memposisikan elemen anak dengan koordinat relatif terhadap area Canvas.
DockPanel Menentukan area di mana Anda dapat mengatur elemen turunan baik secara horizontal maupun vertikal, relatif satu sama lain.
Grid Menentukan area kisi fleksibel yang terdiri dari kolom dan baris.
StackPanel Mengatur elemen turunan dalam satu baris yang dapat diorientasikan secara horizontal atau vertikal.
VirtualizingPanel Menyediakan kerangka kerja untuk elemen Panel 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 properti Orientation.

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

Pertimbangan Performa Tata Letak

Tata letak adalah proses rekursif. Setiap elemen anak dalam koleksi Children akan diproses pada 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 AffectsMeasure yang ditetapkan ke benar. 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, 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 UpdateLayout memaksa pembaruan tata letak rekursif, dan sering tidak diperlukan. Kecuali Anda yakin bahwa pembaruan penuh diperlukan, percayakan pada sistem penataan untuk memanggil metode ini bagi Anda.

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

    Dengan memvirtualisasi koleksi anak, VirtualizingStackPanel hanya 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 sesuai untuk aplikasi WPF pada pengaturan dpi yang berbeda dan membuat aplikasi secara otomatis mengenal dpi.

Namun, independensi dpi ini dapat menyebabkan rendering tepi yang tidak teratur akibat 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 penataan tata letak menyediakan cara untuk menyesuaikan hal ini dengan pembulatan tata letak. Pembulatan tata letak terjadi ketika sistem tata letak membulatkan nilai piksel non-integral selama proses tata letak.

Pembulatan tata letak dinonaktifkan secara default. Untuk mengaktifkan pembulatan tata letak, atur properti UseLayoutRounding ke true pada FrameworkElementapa pun. 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 Selanjutnya

Memahami bagaimana elemen diukur dan disusun adalah langkah pertama dalam memahami tata letak. Untuk informasi selengkapnya tentang elemen Panel yang tersedia, 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.

Lihat juga