Gambaran Umum Objek yang Dapat Di-freezable

Topik ini menjelaskan cara menggunakan dan membuat Freezable objek secara efektif, yang menyediakan fitur khusus yang dapat membantu meningkatkan performa aplikasi. Contoh objek yang dapat di-freezable termasuk kuas, pena, transformasi, geometri, dan animasi.

Apa itu Freezable?

adalah Freezable jenis objek khusus yang memiliki dua status: tidak dibekukan dan dibekukan. Ketika tidak difrozen, tampaknya berulah Freezable seperti objek lain. Ketika dibekukan, tidak Freezable dapat lagi dimodifikasi.

Menyediakan FreezableChanged peristiwa untuk memberi tahu pengamat tentang modifikasi apa pun pada objek. Membekukan Freezable dapat meningkatkan performanya, karena tidak perlu lagi menghabiskan sumber daya untuk pemberitahuan perubahan. Beku Freezable juga dapat dibagikan di seluruh utas, sementara yang tidak dibekukan Freezable tidak dapat.

Freezable Meskipun kelas ini memiliki banyak aplikasi, sebagian besar Freezable objek di Windows Presentation Foundation (WPF) terkait dengan sub-sistem grafis.

Kelas Freezable ini memudahkan penggunaan objek sistem grafis tertentu dan dapat membantu meningkatkan performa aplikasi. Contoh jenis yang mewarisi dari Freezable menyertakan Brushkelas , , Transformdan Geometry . Karena berisi sumber daya yang tidak dikelola, sistem harus memantau objek ini untuk modifikasi, lalu memperbarui sumber daya yang tidak dikelola yang sesuai ketika ada perubahan pada objek asli. Bahkan jika Anda tidak benar-benar memodifikasi objek sistem grafis, sistem masih harus menghabiskan beberapa sumber dayanya untuk memantau objek, jika Anda mengubahnya.

Misalnya, Anda membuat SolidColorBrush kuas dan menggunakannya untuk melukis latar belakang tombol.

Button myButton = new Button();
SolidColorBrush myBrush = new SolidColorBrush(Colors.Yellow);
myButton.Background = myBrush;
Dim myButton As New Button()
Dim myBrush As New SolidColorBrush(Colors.Yellow)
myButton.Background = myBrush

Ketika tombol dirender, sub-sistem grafis WPF menggunakan informasi yang Anda berikan untuk melukis sekelompok piksel untuk membuat tampilan tombol. Meskipun Anda menggunakan kuas warna solid untuk menggambarkan bagaimana tombol harus dicat, kuas warna solid Anda tidak benar-benar melakukan lukisan. Sistem grafis menghasilkan objek tingkat rendah yang cepat untuk tombol dan kuas, dan itu adalah objek yang benar-benar muncul di layar.

Jika Anda memodifikasi kuas, objek tingkat rendah tersebut harus diregenerasi. Kelas yang dapat di-freezable adalah apa yang memberi sikat kemampuan untuk menemukan objek yang dihasilkan dan tingkat rendah yang sesuai dan untuk memperbaruinya ketika berubah. Ketika kemampuan ini diaktifkan, kuas dikatakan "tidak beku."

Metode freezable Freeze memungkinkan Anda menonaktifkan kemampuan pembaruan mandiri ini. Anda dapat menggunakan metode ini untuk membuat kuas menjadi "beku," atau tidak dapat dimodifikasi.

Catatan

Tidak setiap objek Freezable dapat dibekukan. Untuk menghindari pelemparan InvalidOperationException, periksa nilai properti objek CanFreeze Freezable untuk menentukan apakah dapat dibekukan sebelum mencoba membekukannya.

if (myBrush.CanFreeze)
{
    // Makes the brush unmodifiable.
    myBrush.Freeze();
}
If myBrush.CanFreeze Then
    ' Makes the brush unmodifiable.
    myBrush.Freeze()
End If

Ketika Anda tidak perlu lagi memodifikasi freezable, membekukannya memberikan manfaat performa. Jika Anda membekukan kuas dalam contoh ini, sistem grafis tidak perlu lagi memantaunya untuk perubahan. Sistem grafis juga dapat membuat pengoptimalan lain, karena tahu kuas tidak akan berubah.

Catatan

Untuk kenyamanan, objek yang dapat dibekukan tetap tidak beku kecuali Anda secara eksplisit membekukannya.

Menggunakan Freezables

Menggunakan freezable yang tidak beku seperti menggunakan jenis objek lainnya. Dalam contoh berikut, warna diubah SolidColorBrush dari kuning ke merah setelah digunakan untuk melukis latar belakang tombol. Sistem grafis bekerja di belakang layar untuk secara otomatis mengubah tombol dari kuning ke merah saat layar disegarkan.

Button myButton = new Button();
SolidColorBrush myBrush = new SolidColorBrush(Colors.Yellow);
myButton.Background = myBrush;

// Changes the button's background to red.
myBrush.Color = Colors.Red;
Dim myButton As New Button()
Dim myBrush As New SolidColorBrush(Colors.Yellow)
myButton.Background = myBrush


' Changes the button's background to red.
myBrush.Color = Colors.Red

Membekukan Freezable

Untuk membuat Freezable tidak dapat dimodifikasi, Anda memanggil metodenya Freeze . Ketika Anda membekukan objek yang berisi objek yang dapat dibekukan, objek-objek tersebut juga dibekukan. Misalnya, jika Anda membekukan PathGeometry, angka dan segmen yang dikandungnya juga akan dibekukan.

Freezable tidak dapat dibekukan jika salah satu hal berikut ini benar:

  • Ini memiliki properti animasi atau terikat data.

  • Ini memiliki properti yang diatur oleh sumber daya dinamis. (Lihat Sumber Daya XAML untuk informasi selengkapnya tentang sumber daya dinamis.)

  • Ini berisi Freezable sub-objek yang tidak dapat dibekukan.

Jika kondisi ini salah, dan Anda tidak berniat untuk memodifikasi Freezable, maka Anda harus membekukannya untuk mendapatkan manfaat performa yang dijelaskan sebelumnya.

Setelah Anda memanggil metode freezable, metode tersebut Freeze tidak dapat dimodifikasi lagi. Mencoba memodifikasi objek beku menyebabkan dilemparkan InvalidOperationException . Kode berikut melemparkan pengecualian, karena kami mencoba memodifikasi kuas setelah dibekukan.


Button myButton = new Button();
SolidColorBrush myBrush = new SolidColorBrush(Colors.Yellow);

if (myBrush.CanFreeze)
{
    // Makes the brush unmodifiable.
    myBrush.Freeze();
}

myButton.Background = myBrush;

try {

    // Throws an InvalidOperationException, because the brush is frozen.
    myBrush.Color = Colors.Red;
}catch(InvalidOperationException ex)
{
    MessageBox.Show("Invalid operation: " + ex.ToString());
}


Dim myButton As New Button()
Dim myBrush As New SolidColorBrush(Colors.Yellow)

If myBrush.CanFreeze Then
    ' Makes the brush unmodifiable.
    myBrush.Freeze()
End If

myButton.Background = myBrush

Try

    ' Throws an InvalidOperationException, because the brush is frozen.
    myBrush.Color = Colors.Red
Catch ex As InvalidOperationException
    MessageBox.Show("Invalid operation: " & ex.ToString())
End Try

Untuk menghindari melemparkan pengecualian ini, Anda dapat menggunakan IsFrozen metode untuk menentukan apakah dibekukan Freezable .


Button myButton = new Button();
SolidColorBrush myBrush = new SolidColorBrush(Colors.Yellow);

if (myBrush.CanFreeze)
{
    // Makes the brush unmodifiable.
    myBrush.Freeze();
}

myButton.Background = myBrush;

if (myBrush.IsFrozen) // Evaluates to true.
{
    // If the brush is frozen, create a clone and
    // modify the clone.
    SolidColorBrush myBrushClone = myBrush.Clone();
    myBrushClone.Color = Colors.Red;
    myButton.Background = myBrushClone;
}
else
{
    // If the brush is not frozen,
    // it can be modified directly.
    myBrush.Color = Colors.Red;
}


Dim myButton As New Button()
Dim myBrush As New SolidColorBrush(Colors.Yellow)

If myBrush.CanFreeze Then
    ' Makes the brush unmodifiable.
    myBrush.Freeze()
End If

myButton.Background = myBrush


If myBrush.IsFrozen Then ' Evaluates to true.
    ' If the brush is frozen, create a clone and
    ' modify the clone.
    Dim myBrushClone As SolidColorBrush = myBrush.Clone()
    myBrushClone.Color = Colors.Red
    myButton.Background = myBrushClone
Else
    ' If the brush is not frozen,
    ' it can be modified directly.
    myBrush.Color = Colors.Red
End If


Dalam contoh kode sebelumnya, salinan yang dapat dimodifikasi terbuat dari objek beku menggunakan Clone metode . Bagian berikutnya membahas kloning secara lebih rinci.

Catatan

Karena frozen freezable tidak dapat dianimasikan, sistem animasi akan secara otomatis membuat klon objek beku Freezable yang dapat dimodifikasi ketika Anda mencoba untuk menganimasikannya dengan Storyboard. Untuk menghilangkan overhead performa yang disebabkan oleh kloning, biarkan objek tidak dibekukan jika Anda ingin menganimasikannya. Untuk informasi selengkapnya tentang menganimasikan dengan papan cerita, lihat Gambaran Umum Storyboards.

Pembekuan dari Markup

Untuk membekukan objek yang Freezable dideklarasikan dalam markup, Anda menggunakan PresentationOptions:Freeze atribut . Dalam contoh berikut, dinyatakan SolidColorBrush sebagai sumber daya halaman dan dibekukan. Kemudian digunakan untuk mengatur latar belakang tombol.

<Page 
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:PresentationOptions="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options" 
  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  mc:Ignorable="PresentationOptions">

  <Page.Resources>

    <!-- This resource is frozen. -->
    <SolidColorBrush 
      x:Key="MyBrush"
      PresentationOptions:Freeze="True" 
      Color="Red" />
  </Page.Resources>


  <StackPanel>

    <Button Content="A Button" 
      Background="{StaticResource MyBrush}">
    </Button>

  </StackPanel>
</Page>

Untuk menggunakan Freeze atribut , Anda harus memetakan ke namespace opsi presentasi: http://schemas.microsoft.com/winfx/2006/xaml/presentation/options. PresentationOptions adalah awalan yang direkomendasikan untuk memetakan namespace layanan ini:

xmlns:PresentationOptions="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options"

Karena tidak semua pembaca XAML mengenali atribut ini, disarankan agar Anda menggunakan Atribut mc:Ignorable untuk menandai PresentationOptions:Freeze atribut sebagai tidak dapat diabaikan:

xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="PresentationOptions"

Untuk informasi selengkapnya, lihat halaman atribut mc:Ignorable.

"Unfreezing" yang Dapat Dibekukan

Setelah dibekukan, tidak Freezable pernah dapat dimodifikasi atau tidak dibekukan; namun, Anda dapat membuat kloning yang tidak dibekukan menggunakan Clone metode atau CloneCurrentValue .

Dalam contoh berikut, latar belakang tombol diatur dengan kuas dan sikat itu kemudian dibekukan. Salinan yang tidak beku terbuat dari kuas menggunakan metode .Clone Kloning dimodifikasi dan digunakan untuk mengubah latar belakang tombol dari kuning ke merah.

Button myButton = new Button();
SolidColorBrush myBrush = new SolidColorBrush(Colors.Yellow);

// Freezing a Freezable before it provides
// performance improvements if you don't
// intend on modifying it.
if (myBrush.CanFreeze)
{
    // Makes the brush unmodifiable.
    myBrush.Freeze();
}

myButton.Background = myBrush;

// If you need to modify a frozen brush,
// the Clone method can be used to
// create a modifiable copy.
SolidColorBrush myBrushClone = myBrush.Clone();

// Changing myBrushClone does not change
// the color of myButton, because its
// background is still set by myBrush.
myBrushClone.Color = Colors.Red;

// Replacing myBrush with myBrushClone
// makes the button change to red.
myButton.Background = myBrushClone;
Dim myButton As New Button()
Dim myBrush As New SolidColorBrush(Colors.Yellow)

' Freezing a Freezable before it provides
' performance improvements if you don't
' intend on modifying it. 
If myBrush.CanFreeze Then
    ' Makes the brush unmodifiable.
    myBrush.Freeze()
End If


myButton.Background = myBrush

' If you need to modify a frozen brush,
' the Clone method can be used to
' create a modifiable copy.
Dim myBrushClone As SolidColorBrush = myBrush.Clone()

' Changing myBrushClone does not change
' the color of myButton, because its
' background is still set by myBrush.
myBrushClone.Color = Colors.Red

' Replacing myBrush with myBrushClone
' makes the button change to red.
myButton.Background = myBrushClone

Catatan

Terlepas dari metode kloning mana yang Anda gunakan, animasi tidak pernah disalin ke yang baru Freezable.

Metode Clone dan CloneCurrentValue menghasilkan salinan mendalam dari freezable. Jika freezable berisi objek lain yang dapat dibekukan, mereka juga dikloning dan dibuat dapat dimodifikasi. Misalnya, jika Anda mengkloning beku untuk membuatnya dapat dimodifikasi, angka dan segmen yang dikandungnya PathGeometry juga disalin dan dibuat dapat dimodifikasi.

Membuat Kelas Freezable Anda Sendiri

Kelas yang berasal dari Freezable mendapatkan fitur berikut.

  • Status khusus: baca-saja (beku) dan status bisa-tulis.

  • Keamanan utas: beku Freezable dapat dibagikan di seluruh utas.

  • Pemberitahuan perubahan terperinci: Tidak seperti yang lain DependencyObject, objek Freezable menyediakan pemberitahuan perubahan saat nilai sub-properti berubah.

  • Kloning yang mudah: kelas Freezable telah menerapkan beberapa metode yang menghasilkan klon mendalam.

Freezable adalah jenis DependencyObject, dan oleh karena itu menggunakan sistem properti dependensi. Properti kelas Anda tidak harus menjadi properti dependensi, tetapi menggunakan properti dependensi akan mengurangi jumlah kode yang harus Anda tulis, karena Freezable kelas dirancang dengan mengingat properti dependensi. Untuk informasi selengkapnya tentang sistem properti dependensi, lihat Gambaran Umum Properti Dependensi.

Setiap Freezable subkelas harus mengambil alih CreateInstanceCore metode . Jika kelas Anda menggunakan properti dependensi untuk semua datanya, Anda sudah selesai.

Jika kelas Anda berisi anggota data properti non-dependensi, Anda juga harus mengambil alih metode berikut:

Anda juga harus mengamati aturan berikut untuk mengakses dan menulis ke anggota data yang bukan properti dependensi:

  • Di awal API apa pun yang membaca anggota data properti non-dependensi, panggil ReadPreamble metode .

  • Di awal API apa pun yang menulis anggota data properti non-dependensi, panggil metode .WritePreamble (Setelah Anda memanggil WritePreamble API, Anda tidak perlu melakukan panggilan ReadPreamble tambahan jika Anda juga membaca anggota data properti non-dependensi.)

  • WritePostscript Panggil metode sebelum keluar dari metode yang menulis ke anggota data properti non-dependensi.

Jika kelas Anda berisi anggota data properti non-dependensi yang merupakan DependencyObject objek, Anda juga harus memanggil OnFreezablePropertyChanged metode setiap kali Anda mengubah salah satu nilainya, bahkan jika Anda mengatur anggota ke null.

Catatan

Sangat penting bagi Anda untuk memulai setiap Freezable metode yang Anda ambil alih dengan panggilan ke implementasi dasar.

Untuk contoh kelas kustom Freezable , lihat Sampel Animasi Kustom.

Baca juga