ContentControl และ ContentPresenter แตกต่างกันอย่างไร


208

ฉันไม่แน่ใจว่าเมื่อไรที่ฉันควรใช้ContentPresenterแทนContentControl(และในทางกลับกัน) ในขณะนี้ฉันใช้ContentControlเวลาส่วนใหญ่ของฉันDataTemplateอยู่เสมอ เมื่อไหร่จะContentPresenterเป็นทางเลือกที่ดีกว่า และทำไม?

คำตอบ:


164

ContentControlเป็นคลาสพื้นฐานสำหรับการควบคุมที่มีองค์ประกอบอื่น ๆ และมีContent-property (ตัวอย่างเช่นButton)

ContentPresenter ถูกใช้ภายในเทมเพลตควบคุมเพื่อแสดงเนื้อหา

ContentControlเมื่อใช้โดยตรง (ควรใช้เป็นคลาสพื้นฐาน) มีเทมเพลตควบคุมที่ใช้ ContentPresenter เพื่อแสดงเนื้อหา

กฎง่ายๆของฉัน (ไม่สามารถใช้ได้ในทุกกรณีใช้วิจารณญาณของคุณ):

  1. การControlTemplateใช้งานภายในContentPresenter
  2. นอกControlTemplate(รวมถึงDataTemplateและนอกแม่แบบ) พยายามอย่าใช้สิ่งใด ๆ หากคุณต้องการคุณต้องชอบContentPresenter
  3. คลาสย่อยContentControlถ้าคุณกำลังสร้างตัวควบคุม "lookless" แบบกำหนดเองที่เนื้อหาโฮสต์และคุณไม่สามารถรับผลลัพธ์เดียวกันได้โดยการเปลี่ยนเทมเพลตของตัวควบคุมที่มีอยู่ (ซึ่งควรหายากมาก)

1
นั่นหมายความว่าโดยทั่วไปแล้วฉันควรใช้ ContentPresenter ภายใน DataTemplates ของฉันเพราะมีน้ำหนักเบากว่า (แต่เทียบเท่ากับการใช้งานได้ดีเมื่อใช้ใน DataTemplate แบบนี้) จากนั้นใช้ ContentControl เป็นคลาสพื้นฐานถ้าฉันเขียนตัวควบคุมใหม่
Wilka

ฉันได้แก้ไขคำตอบที่มีรายละเอียดมากขึ้นเมื่อฉันจะใช้ ContentPresenter และเมื่อ ContentControl
Nir

1
ตกลงฉันคิดว่าควรใช้ ContentPresenter ในเทมเพลตแทน ContentControl แต่ทำไม
sll

32
@sll - ContentControl เป็นคลาสพื้นฐานสำหรับทุกการควบคุมที่แสดง "เนื้อหา" (ตัวอย่าง: Label), ContentPresenter เป็นรหัสที่ใช้ภายในโดย ContentControl เพื่อแสดงเนื้อหา - ดังนั้น: 1. ContentPresenter มีน้ำหนักเบามากขึ้น 2. ContentPresenter ถูกออกแบบมาเพื่อ ถูกนำมาใช้ภายในแม่แบบการควบคุมและ 3 ContnetPresenter ถูกออกแบบมาเพื่อนำมาใช้ตามที่เป็นในขณะที่ ContentControl ถูกออกแบบมาเพื่อขยาย (สืบทอดมาจาก)
Nir

23
ContentPresenter ทำงานแตกต่างจาก ContentControl เมื่อมีการตั้งค่าคุณสมบัติเนื้อหา เมื่อคุณตั้งค่าคุณสมบัติเนื้อหาของ ContentPresenter การเปลี่ยนแปลง DataContext เพื่อให้ตรงกับคุณสมบัติเนื้อหา แต่ DataContext ของ ContentControl จะไม่ได้รับผลกระทบ สิ่งนี้สำคัญหากคุณมีคุณสมบัติอื่น ๆ บน ContentPresenter ตั้งค่าผ่านการเชื่อมโยงเนื่องจากเมื่อ DataContext เปลี่ยนการเชื่อมโยงทั้งหมดจะใช้สิ่งนั้นเป็นแหล่งข้อมูล
user195275

25

ContentPresenter มักจะใช้ใน ControlTemplate เป็นตัวยึดตำแหน่งที่จะพูดว่า "ใส่เนื้อหาจริงที่นี่"

ContentControl สามารถใช้ได้ทุกที่โดยไม่จำเป็นต้องอยู่ในเทมเพลต มันจะรับ DataTemplate ใด ๆ ที่กำหนดไว้สำหรับประเภทของเนื้อหาที่ได้รับมอบหมาย


6
ContentPresenter จะไม่ทำให้ DataTemplate ใช้กับเนื้อหาของมันด้วยหรือไม่ นั่นไม่ใช่หนึ่งในวัตถุประสงค์หลักหรือ?
Drew Noakes

1
mmm ... ใช่แล้ว อย่างไรก็ตามคำอธิบาย Bea Stollnitz เป็นมากดีกว่าฉัน;)
โทมัส Levesque

คำตอบสั้น ๆ ของคุณดูเหมือนจะสรุปได้อย่างรวดเร็ว: ฉันเชื่อว่าการออกแบบทั้งหมดของ ContentPresenter นั้นก็คือ "ใช้" อัตราเงินเฟ้อ DataTemplate --- ดูเหมือนว่าจะมีงานเพียงอย่างเดียวในการค้นหาและขยายเทมเพลตโดยตั้งค่า DataContext และพยายามที่จะ "หายไป" ให้มากที่สุดเท่าที่จะเป็นไปได้ (คิดว่าคุณยังสามารถผูกภายในเท็มเพลตที่สูงเกินจริงไปยังคุณสมบัติโดยรอบเช่นคุณสมบัติ TextElement ซึ่งมาจาก ContentPresenter) คุณไม่จำเป็นต้องกังวลเกี่ยวกับสิ่งอื่นและมันทำให้พองแม่แบบในทางที่ค่อนข้างบาง (ฉันกำลังมองหาที่บางที่สุด!)
สตีเวน Coco

9

ฉันเพิ่งเขียนบทความในบล็อกของฉันเกี่ยวกับการควบคุมทั้งสองนี้:

ContentPresenter vs ContentControl (แก้ไข: ลิงก์เสียแทนที่ด้วยรุ่นที่เก็บถาวร)

ContentPresenter.ContentSourceคือสิ่งที่จริงทำให้ความแตกต่างที่ใหญ่ที่สุดระหว่างสองชั้น คุณสมบัติแหล่งเนื้อหาทำให้รู้สึกได้เฉพาะภายใน ControlTemplate; มันเป็นตัวกำหนดคุณสมบัติของ TemplatedParent ที่เนื้อหาควรถูกแมปด้วย ตัวอย่างเช่นหากตัวควบคุมมีคุณสมบัติการพึ่งพาMyProperty1เราอาจพบสิ่งต่อไปนี้ภายในControlTemplate:

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

เนื้อหาของ ContentPresenter MyProperty1ที่จะได้รับค่าของ

โปรดทราบว่าหากชื่อของสถานที่Contentนั้นไม่จำเป็นต้องระบุContentSourceเนื่องจากเป็นค่าเริ่มต้น

สำหรับผู้ที่รู้ว่า angularJs: สิ่งนี้คล้ายกับการแปลงเพศเป็น mecanism


2

เป็นคำถามเก่า แต่ฉันเพิ่งจะเสร็จสิ้นการพัฒนา Tile Control แบบเคลื่อนไหวเทมเพลตที่ใช้แอพสากลดูที่รหัสนี้จาก Phone WP7 / 8 SDK เก่า:

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

ที่นี่คุณสามารถเห็น ContentControl คือ Container และ Presenter สำหรับแสดงเนื้อหา ในกรณีส่วนใหญ่ ControlTemplate จะเป็นตู้คอนเทนเนอร์ แต่ถ้าคุณต้องการของคุณในControlTemplateภาชนะอื่นที่คุณสามารถใส่ตู้คอนเทนเนอร์พิเศษ: ในนั้นและสำหรับการนำเสนอเนื้อหาที่แยกต่างหากContentControl ContentPresenterหากคุณไม่ต้องการภาชนะแยกต่างหากให้ใช้ControlTemplateและControlPresentersสำหรับการแสดงบล็อคเนื้อหาอย่างน้อยนั่นคือสิ่งที่พวกที่ Microsoft ทำเมื่อพัฒนา WP7 / 8 SDK ContentControl ยังสามารถใช้สำหรับการแสดงเนื้อหา แต่ก็ทำหน้าที่เป็นทั้งคอนเทนเนอร์และผู้นำเสนอ ดังนั้นในโค้ดตัวอย่างด้านบนจุดประสงค์ของมันจึงแยกใน Container และ Presenter ในตัวอย่างแบบไดนามิกคุณสามารถแสดงคอนเทนเนอร์ (มันสามารถมีพื้นหลังที่ว่างเปล่าหรือสิ่งที่ยังไม่ได้มี) และจากนั้นเติมด้วยเนื้อหาผู้นำเสนอแบบไดนามิก คอนเทนเนอร์มีขนาด (ความกว้างความสูง ฯลฯ ) คุณวางคุณสมบัติเหล่านั้นไว้ในการควบคุมคอนเทนเนอร์และนำเสนอเนื้อหาในนั้น ในตัวอย่าง ContentControl กำหนดสิ่งที่ต้องทำกับเนื้อหาของผู้นำเสนอ


1

บางครั้งตัวอย่างง่ายกว่าศัพท์แสงทางทฤษฎี ในเว็บไซต์ MS (เลื่อนไปที่ด้านล่าง: http://msdn.microsoft.com/en-us/library/system.windows.controls.contentpresenter(v=vs.110).aspx ) มันใช้ปุ่มเป็น ตัวอย่าง. ปุ่มมี ContentControl ซึ่งช่วยให้คุณวางตัวควบคุมหนึ่งตัวหรือตัวควบคุมแบบกำหนดเองที่อาจเป็นรูปภาพ, ข้อความ, กล่องกาเครื่องหมาย, StackPanel, กริดได้ทุกอย่าง

หลังจากการปรับแต่งปุ่มตอนนี้บน Xaml คุณสามารถเขียน

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

ในโค้ดตัวอย่างข้างต้น "my: Button.Content" คือ ContentControl AnotherControl จะไปยังที่ที่คุณระบุว่า ContentPresenter นั้นอยู่ที่ไหน

ในทำนองเดียวกันเมื่อเปรียบเทียบ TextBox กับ TextBlock TextBox จะมี ContentPresenter สำหรับคุณในการคัดลอกเนื้อหาเช่นเดียวกับตัวอย่างปุ่มด้านบนในขณะที่ TextBlock ไม่มี TextBlock อนุญาตให้คุณป้อนข้อความเท่านั้น


2
Buttonไม่ได้มี a [ ContentControl] (msdn.microsoft.com/en-us/library/system.windows.controls.contentcontrol (v = vs.110) .aspx) มันเป็นContentControl (สืบทอดจาก) Button มี ContentPresenterโปรดทราบว่าคุณสามารถทำได้ด้วยมาตรฐานButtonไม่จำเป็นต้องปรับแต่ง
หรือผู้ทำแผนที่

แต่ไม่เกี่ยวข้องกับการที่คำตอบนี้ไม่ได้อธิบายว่าการและเหตุผลแทนContentPresenterการContentControlไม่สามารถใช้เพียงเช่นกันในการแสดงเนื้อหาของControlTemplate Buttonเช่นนี้จะไม่ตอบคำถาม
หรือผู้ทำแผนที่
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.