Apa perbedaan antara ContentControl dan ContentPresenter?

208

Saya tidak yakin ketika saya harus menggunakan ContentPresenterbukan ContentControl(dan sebaliknya). Saat ini, saya menggunakan ContentControlhampir setiap waktu di komputer saya DataTemplate. Kapan ContentPresenterpilihan yang lebih baik? dan mengapa?

Wilka
sumber

Jawaban:

164

ContentControladalah kelas dasar untuk kontrol yang mengandung elemen lain dan memiliki Content-properti (misalnya, Button).

ContentPresenter digunakan di dalam template kontrol untuk menampilkan konten.

ContentControl, ketika digunakan secara langsung (seharusnya digunakan sebagai kelas dasar), memiliki templat kontrol yang menggunakan ContentPresenter untuk menampilkan kontennya.

Aturan praktis saya (tidak berlaku dalam setiap kasus, gunakan penilaian Anda):

  1. ControlTemplatePenggunaan di dalamContentPresenter
  2. Di luar ControlTemplate(termasuk DataTemplatedan di luar templat) cobalah untuk tidak menggunakannya, jika perlu, Anda harus memilihContentPresenter
  3. Subkelas ContentControljika Anda membuat kontrol "tidak terlihat" khusus untuk konten host itu dan Anda tidak bisa mendapatkan hasil yang sama dengan mengubah templat kontrol yang ada (yang seharusnya sangat langka).
Nir
sumber
1
Apakah itu berarti bahwa, secara umum, saya mungkin harus menggunakan ContentPresenter di dalam DataTemplates saya, karena itu lebih ringan (tapi secara fungsional setara ketika digunakan dalam DataTemplate seperti ini)? Kemudian gunakan saja ContentControl sebagai kelas dasar jika saya menulis kontrol baru?
Wilka
Saya telah mengedit jawaban dengan lebih detail ketika saya akan menggunakan ContentPresenter dan ketika ContentControl
Nir
1
Oke, saya punya ide bahwa ContentPresenter harus digunakan dalam templat alih-alih ContentControl, tapi mengapa?
sll
32
@sll - ContentControl adalah kelas dasar untuk setiap kontrol yang menampilkan "konten" (contoh: Label), ContentPresenter adalah kode yang digunakan secara internal oleh ContentControl untuk menampilkan konten - jadi: 1. ContentPresenter lebih ringan, 2. ContentPresenter dirancang untuk digunakan di dalam template kontrol dan 3. ContnetPresenter dirancang untuk digunakan apa adanya sementara ContentControl dirancang untuk diperluas (diwarisi dari)
Nir
23
ContentPresenter berperilaku berbeda dari ContentControl ketika datang untuk mengatur properti Content. Saat Anda menyetel properti Konten ContentPresenter, DataContext-nya berubah untuk mencocokkan dengan properti Content, tetapi DataContext ContentControl tetap tidak terpengaruh. Ini penting jika Anda memiliki properti lain di ContentPresenter yang ditetapkan melalui pengikatan, karena begitu DataContext berubah, semua binding menggunakannya sebagai sumber.
user195275
25

ContentPresenter biasanya digunakan dalam ControlTemplate, sebagai pengganti untuk mengatakan "taruh konten aktual di sini".

ContentControl dapat digunakan di mana saja, tidak harus dalam templat. Ini akan mengambil DataTemplate apa pun yang ditentukan untuk jenis konten yang ditugaskan padanya

Thomas Levesque
sumber
6
Tidakkah seorang ContentPresenter juga menyebabkan DataTemplate diterapkan pada kontennya? Bukankah itu salah satu tujuan utamanya?
Drew Noakes
1
mmm ... ya, mungkin. Pokoknya, penjelasan Bea Stollnitz ini jauh lebih baik dari saya;)
Thomas Levesque
Jawaban singkat Anda sepertinya meringkasnya dengan cepat: Saya percaya seluruh desain ContentPresenter adalah dengan hanya "mengimplementasikan" inflasi DataTemplate --- tampaknya memiliki satu-satunya pekerjaan hanya menemukan dan menggembungkan templat, mengatur DataContext juga; dan kemudian mencoba untuk "menghilang" sebanyak mungkin (MESKIPUN Anda MASIH dapat mengikat dalam templat yang digembungkan ke properti sekitar seperti properti TextElement, yang berasal dari ContentPresenter). Anda tidak perlu khawatir tentang hal-hal lain, dan itu hanya mengembang template dengan cara yang relatif ramping. (Saya mencari yang tertipis!)
Steven Coco
9

Baru-baru ini saya menulis posting di blog saya mengenai dua kontrol ini:

ContentPresenter vs ContentControl (EDIT: Tautan rusak diganti dengan versi yang diarsipkan.)

The ContentPresenter.ContentSource adalah apa yang sebenarnya membuat perbedaan terbesar antara dua kelas. Properti ContentSource masuk akal hanya dalam ControlTemplate; itu menentukan properti TemplatedParent mana konten harus dipetakan. Misalnya, jika kontrol berisi properti dependensi MyProperty1, maka kami mungkin menemukan yang berikut ini di dalamnya ControlTemplate:

<ControlTemplate TargetType="MyControl" >
    [...]
       <ContentPresenter ContentSource="MyProperty1" />
    [...]
</ControlTemplate>

Konten ContentPresenter akan menerima nilai MyProperty1.

Harap dicatat bahwa jika nama properti adalah Content, tidak perlu ditentukan ContentSourcekarena ini adalah nilai default.

Bagi mereka yang tahu angular: ini mirip dengan transclude mecanism.

Charles HETIER
sumber
2

Ini pertanyaan lama tapi saya baru saja selesai mengembangkan Tile Control animasi, berbasis template untuk aplikasi universal, lihat kode ini dari Phone WP7 / 8 SDK lama:

<ContentControl x:Name="contentControl" HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch" VerticalAlignment="Stretch" VerticalContentAlignment="Stretch">
    <ContentPresenter x:Name="contentPresenter" CacheMode="BitmapCache"/>
</ContentControl>

Di sini Anda dapat melihat ContentControl adalah Container dan Presenter untuk menampilkan konten. Dalam kebanyakan kasus, ControlTemplate akan menjadi Wadah tetapi jika Anda ingin di ControlTemplatewadah lain Anda dapat menempatkan Wadah tambahan: ContentControldi dalamnya dan untuk menyajikan konten secara terpisah ContentPresenter. Jika Anda tidak membutuhkan wadah yang terpisah maka gunakan saja ControlTemplatedanControlPresentersuntuk menampilkan blok konten setidaknya itulah yang dilakukan orang-orang di Microsoft ketika mereka mengembangkan WP7 / 8 SDK. ContentControl juga dapat digunakan untuk menampilkan konten, tetapi kemudian berfungsi sebagai wadah dan presenter. Jadi, dalam kode contoh di atas, tujuannya dibagi dalam Container dan Presenter. Dalam sampel dinamis, Anda dapat menampilkan wadah (dapat memiliki latar belakang kosong atau sesuatu yang belum ada di sana) dan kemudian secara dinamis mengisinya dengan konten presenter. Wadah memiliki dimensi (lebar, tinggi, dll.), Anda menempatkan properti itu di kontrol wadah dan menyajikan konten di dalamnya. Dalam sampel, ContentControl menentukan apa yang harus dilakukan dengan konten presenter.

Herman Van Der Blom
sumber
1

Terkadang contoh lebih mudah daripada jargon teoretis. Dalam situs web MS (Gulir ke bawah: http://msdn.microsoft.com/en-us/library/system.windows.controls.contentpresenter(v=vs.110).aspx ), ia menggunakan tombol sebagai sebuah contoh. Sebuah Tombol memiliki ContentControl, yang memungkinkan Anda untuk menempatkan satu kontrol atau kontrol kustom yang bisa berupa Gambar, Teks, Kotak Centang, StackPanel, Kotak, apa pun.

Setelah penyesuaian Tombol, sekarang di Xaml, Anda dapat menulis

<my:Button>
   <my:Button.Content>
      <my:AnotherControl>
   </my:Button.Content>
</my:Button>

Dalam contoh kode di atas, "my: Button.Content" adalah ContentControl. AnotherControl akan ditempatkan pada apa yang telah Anda tentukan di mana ContentPresenter berada.

Demikian pula, ketika membandingkan TextBox dan TextBlock, TextBox memiliki ContentPresenter untuk Anda memasukkan barang-barang di dalamnya seperti contoh Tombol di atas sedangkan TextBlock tidak. TextBlock hanya memungkinkan Anda memasukkan teks.

Wayne Lo
sumber
2
A Buttontidak memiliki [ ContentControl] (msdn.microsoft.com/en-us/library/system.windows.controls.contentcontrol (v = vs.110) .aspx), itu adalah (diturunkan dari) ContentControl. The Button memiliki sebuah ContentPresenter. Perhatikan bahwa Anda dapat melakukannya dengan standar Button, tidak perlu menyesuaikannya.
ATAU Mapper
Tetapi tidak ada hubungannya dengan itu, jawaban ini tidak menjelaskan apakah dan mengapa, alih-alih ContentPresenter, a ContentControltidak dapat digunakan dengan baik di ControlTemplateuntuk menampilkan konten Button. Dengan demikian, itu tidak menjawab pertanyaan.
ATAU Mapper