Bagikan melalui


Gambaran Umum Objek yang Dapat Dibekukan

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

Apa itu benda yang dapat dibekukan?

Freezable adalah jenis objek khusus yang memiliki dua status: tidak beku dan beku. Ketika dicairkan, Freezable tampaknya berperilaku seperti objek lainnya. Ketika dibekukan, Freezable tidak dapat lagi dimodifikasi.

Freezable menyediakan peristiwa Changed 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. Freezable beku juga dapat dibagikan di seluruh utas, sementara Freezable yang tidak dibekukan tidak dapat.

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

Kelas Freezable memudahkan penggunaan objek sistem grafis tertentu dan dapat membantu meningkatkan performa aplikasi. Contoh jenis yang mewarisi dari Freezable termasuk kelas Brush, Transform, dan 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 kuas SolidColorBrush 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 dibekukan memberi kuas kemampuan untuk menemukan objek tingkat rendah yang dihasilkan dan memperbaruinya ketika berubah. Ketika kemampuan ini diaktifkan, kuas dikatakan "tidak beku."

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

Nota

Tidak setiap objek Freezable dapat dibekukan. Untuk menghindari menghasilkan InvalidOperationException, periksa nilai dari properti CanFreeze pada objek 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 objek yang bisa dibekukan, membekukannya dapat meningkatkan kinerja. 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.

Nota

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

Menggunakan Freezables

Menggunakan freezable yang tidak dibekukan seperti menggunakan objek jenis lainnya. Dalam contoh berikut, warna SolidColorBrush diubah 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 berikutnya.

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 Barang yang Dapat Dibekukan

Untuk membuat Freezable tidak dapat dimodifikasi, Anda memanggil metode 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.

yang dapat dibekukan tidak dapat dibekukan jika salah satu hal berikut 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.

Ketika Anda memanggil metode Freeze dari objek freezable, objek tersebut tidak dapat dimodifikasi lagi. Mencoba memodifikasi objek yang telah dibekukan akan menyebabkan InvalidOperationException dilemparkan. 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 metode IsFrozen untuk menentukan apakah Freezable dibekukan.


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 metode Clone. Bagian berikutnya membahas kloning secara lebih rinci.

Nota

Karena freezable yang beku tidak dapat dianimasikan, sistem animasi akan secara otomatis membuat klon yang dapat dimodifikasi dari objek Freezable yang beku saat Anda mencoba menganimasikannya dengan Storyboard. Untuk menghilangkan overhead performa yang disebabkan oleh kloning, biarkan objek tidak dibekukan jika Anda ingin menganimasikannya. Untuk informasi selengkapnya tentang animasi dengan storyboard, lihat Ikhtisar Storyboard .

Pembekuan dari Markup

Untuk membekukan objek Freezable yang dideklarasikan dalam markup, Anda menggunakan atribut PresentationOptions:Freeze. Dalam contoh berikut, SolidColorBrush dinyatakan 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 atribut Freeze, Anda harus memetakan ke namespace opsi presentasi: http://schemas.microsoft.com/winfx/2006/xaml/presentation/options. PresentationOptions adalah awalan yang direkomendasikan untuk memetakan namespace 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 atribut PresentationOptions:Freeze sebagai tidak dapat diabaikan:

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

Untuk informasi selengkapnya, lihat halaman atribut mc:Ignorable.

Melepaskan Pembekuan pada Sesuatu yang Bisa Dibekukan

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

Dalam contoh berikut, latar belakang tombol diatur dengan kuas dan sikat itu kemudian dibekukan. Salinan tidak beku dibuat 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

Nota

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

Metode Clone dan CloneCurrentValue menghasilkan salinan lengkap dari objek yang dapat dibekukan. Jika freezable berisi objek lain yang dapat dibekukan, mereka juga dikloning dan dibuat dapat dimodifikasi. Misalnya, jika Anda mengkloning PathGeometry yang beku untuk membuatnya dapat dimodifikasi, maka angka dan segmen yang dikandungnya juga disalin dan 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 thread: Freezable yang dibekukan dapat dibagikan antar thread.

  • Pemberitahuan perubahan terperinci: Tidak seperti DependencyObjectlainnya, 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 karenanya 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 kelas Freezable dirancang dengan mengingat properti dependensi. Untuk informasi selengkapnya tentang sistem properti dependensi, lihat Gambaran Umum Properti Dependensi .

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

Jika kelas Anda berisi anggota data yang bukan properti dependensi, Anda juga harus mengganti fungsi dari metode-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 metode ReadPreamble.

  • Pada awal setiap API yang memasukkan anggota data properti non-dependensi, panggil metode WritePreamble. (Setelah memanggil WritePreamble dalam API, Anda tidak perlu melakukan panggilan tambahan ke ReadPreamble jika Anda juga membaca data anggota properti non-dependensi.)

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

Jika kelas Anda berisi objek DependencyObject yang bukan properti ketergantungan, Anda juga harus memanggil metode OnFreezablePropertyChanged setiap kali Anda mengubah salah satu nilainya, bahkan jika Anda menetapkan anggota tersebut ke null.

Nota

Sangat penting bagi Anda untuk memulai setiap metode Freezable yang Anda override dengan melakukan panggilan ke implementasi dasarnya.

Untuk contoh kelas Freezable kustom, lihat Sampel Animasi Kustom .

Lihat juga