Sự khác biệt giữa ContentControl và ContentPresenter là gì?


208

Tôi không chắc chắn khi nào tôi nên sử dụng ContentPresenterthay vì ContentControl(và ngược lại). Hiện tại, tôi đang sử dụng ContentControlkhá nhiều thời gian trong DataTemplates của tôi . Khi nào sẽ ContentPresenterlà một lựa chọn tốt hơn? và tại sao?

Câu trả lời:


163

ContentControllà một lớp cơ sở cho các điều khiển có chứa các phần tử khác và có Content-property (ví dụ Button:).

ContentPresenter được sử dụng bên trong các mẫu điều khiển để hiển thị nội dung.

ContentControl, khi được sử dụng trực tiếp (được cho là được sử dụng làm lớp cơ sở), có một mẫu điều khiển sử dụng ContentPresenter để hiển thị nội dung của nó.

Quy tắc ngón tay cái của tôi (không áp dụng trong mọi trường hợp, sử dụng phán đoán của bạn):

  1. ControlTemplateSử dụng bên trongContentPresenter
  2. Bên ngoài ControlTemplate(bao gồm DataTemplatevà các mẫu bên ngoài) cố gắng không sử dụng bất kỳ mẫu nào trong số chúng, nếu bạn cần, bạn phải thíchContentPresenter
  3. Phân lớp ContentControlnếu bạn đang tạo một điều khiển "không nhìn" tùy chỉnh mà lưu trữ nội dung và bạn không thể nhận được kết quả tương tự bằng cách thay đổi mẫu của điều khiển hiện có (điều này cực kỳ hiếm).

1
Điều đó có nghĩa là, nói chung, có lẽ tôi nên sử dụng ContentPresenter bên trong DataTemsheet của mình, vì nó nhẹ hơn (nhưng tương đương về mặt chức năng khi được sử dụng trong DataTemplate như thế này)? Sau đó, chỉ sử dụng ContentControl làm lớp cơ sở nếu tôi đang viết một điều khiển mới?
Wilka

Tôi đã chỉnh sửa câu trả lời với nhiều chi tiết hơn khi tôi sẽ sử dụng ContentPresenter và khi ContentControl
Nir

1
Ok tôi có ý tưởng rằng ContentPresenter nên được sử dụng trong các mẫu thay vì ContentControl, nhưng tại sao?
sll

32
@sll - ContentControl là lớp cơ sở cho mọi điều khiển hiển thị "nội dung" (ví dụ: Nhãn), ContentPresenter là mã được ContentControl sử dụng để hiển thị nội dung - vì vậy: 1. ContentPresenter nhẹ hơn, 2. ContentPresenter được thiết kế để được sử dụng bên trong các mẫu điều khiển và 3. ContnetPresenter được thiết kế để sử dụng nguyên trạng trong khi ContentControl được thiết kế để được mở rộng (kế thừa từ)
Nir

23
ContentPresenter hoạt động khác với ContentControl khi có tập thuộc tính Content. Khi bạn đặt thuộc tính Nội dung của ContentPresenter, DataContext của nó sẽ thay đổi để phù hợp với thuộc tính Nội dung, nhưng DataContext của ContentControl vẫn không bị ảnh hưởng. Điều này quan trọng nếu bạn có các thuộc tính khác trên ContentPresenter được đặt thông qua liên kết, bởi vì một khi DataContext thay đổi, tất cả các ràng buộc sử dụng đó làm nguồn.
195275

25

ContentPresenter thường được sử dụng trong ControlTemplate, như một trình giữ chỗ để nói "đặt nội dung thực tế ở đây".

ContentControl có thể được sử dụng ở bất cứ đâu, không nhất thiết phải trong một mẫu. Nó sẽ chọn bất kỳ DataTemplate nào được xác định cho loại nội dung được gán cho nó


6
Không phải ContentPresenter cũng sẽ khiến DataTemplate được áp dụng cho nội dung của nó chứ? Đó không phải là một trong những mục đích chính của nó sao?
vẽ Noakes

1
Ừm ... ừ, có lẽ. Dù sao, lời giải thích của Bea Stollnitz tốt hơn tôi nhiều;)
Thomas Levesque

Câu trả lời ngắn gọn của bạn dường như tóm tắt nhanh chóng: Tôi tin rằng toàn bộ thiết kế của ContentPresenter chỉ đơn giản là "thực hiện" lạm phát DataTemplate --- dường như chỉ có công việc duy nhất là định vị và thổi phồng mẫu, cũng thiết lập DataContext; và cố gắng sau đó để "biến mất" càng nhiều càng tốt (THÌ BẠN VẪN có thể liên kết trong khuôn mẫu bị thổi phồng với các thuộc tính xung quanh như các thuộc tính TextEuity, sau đó đến từ ContentPresenter). Bạn không cần phải lo lắng về những thứ khác, và nó chỉ thổi phồng mẫu theo cách tương đối mỏng. (Tôi đang tìm kiếm người gầy nhất!)
Steven Coco

9

Gần đây tôi đã viết một bài đăng trên blog của mình về hai điều khiển này:

ContentPresenter vs ContentControl (EDIT: Liên kết bị hỏng được thay thế bằng phiên bản lưu trữ.)

Các ContentPresenter.ContentSource là những gì thực sự làm cho sự khác biệt lớn nhất giữa hai lớp. Thuộc tính ContentSource chỉ có ý nghĩa trong ControlTemplate; nó xác định thuộc tính TemplatedParent nào mà nội dung sẽ được ánh xạ. Ví dụ: nếu một điều khiển chứa thuộc tính phụ thuộc MyProperty1, thì chúng ta có thể tìm thấy các điều sau trong phạm vi của nó ControlTemplate:

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

Nội dung của ContentPresenter sẽ nhận được giá trị của MyProperty1.

Xin lưu ý rằng nếu tên của tài sản là Content, không cần chỉ định ContentSourcevì đó là giá trị mặc định.

Đối với những người biết angularJs: điều này tương tự như mecanism xuyên.


2

Đó là một câu hỏi cũ nhưng tôi vừa hoàn thành việc phát triển một Điều khiển Ngói hoạt hình, mẫu dựa trên một ứng dụng phổ quát, hãy xem mã này từ SDK Điện thoại WP7 / 8 cũ:

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

Tại đây bạn có thể thấy ContentControl là Container và Presenter để hiển thị nội dung. Trong hầu hết các trường hợp, ControlTemplate sẽ là Container nhưng nếu bạn muốn trong ControlTemplatemột container khác, bạn có thể đặt một Container bổ sung: ContentControltrong đó và để trình bày nội dung một cách riêng biệt ContentPresenter. Nếu bạn không cần một container riêng thì chỉ cần sử dụng ControlTemplateControlPresentersđể hiển thị các khối nội dung ít nhất đó là những gì mà những người ở Microsoft đã làm khi họ phát triển SDK WP7 / 8. ContentControl cũng có thể được sử dụng để hiển thị nội dung nhưng sau đó nó đóng vai trò là người chứa và người trình bày. Vì vậy, trong mã mẫu trên mục đích của nó được chia trong Container và Presenter. Trong các mẫu động, bạn có thể hiển thị vùng chứa (nó có thể có nền trống hoặc thứ gì đó chưa có) và sau đó tự động điền nó với nội dung của người trình bày. Một container có kích thước (chiều rộng, chiều cao, v.v.), bạn đặt các thuộc tính đó vào điều khiển container và trình bày nội dung trên nó. Trong mẫu, ContentControl xác định những gì phải được thực hiện với nội dung của người trình bày.


1

Đôi khi một ví dụ dễ hơn thuật ngữ lý thuyết. Trong một trang web MS (Di chuyển xuống dưới cùng: http://msdn.microsoft.com/en-us/l Library / system.windows.controls.contentpresenter (v = vs.110 ) .aspx ), nó sử dụng một nút như một ví dụ. Nút có ContentControl, cho phép bạn đặt một điều khiển hoặc điều khiển tùy chỉnh có thể là Hình ảnh, Văn bản, CheckBox, StackPanel, Grid, bất cứ điều gì.

Sau khi tùy chỉnh Nút, giờ đây trên Xaml, bạn có thể viết

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

Trong mã ví dụ trên, "my: Button.Content" là ContentControl. AnotherControl sẽ là nơi bạn đã chỉ định nơi ContentPresenter đang ở.

Tương tự, khi so sánh TextBox và TextBlock, TextBox có ContentPresenter để bạn nhét vào đó giống như ví dụ về Nút trên trong khi TextBlock không có. TextBlock chỉ cho phép bạn nhập văn bản.


2
A Buttonkhông [ ContentControl] (msdn.microsoft.com/en-us/l Library / system.windows.controls.contentcontrol (v = vs.110) .aspx), đó là một (kế thừa từ) ContentControl. Các Button một ContentPresenter. Lưu ý rằng bạn có thể làm điều đó với tiêu chuẩn Button, không cần phải tùy chỉnh nó.
HOẶC Mapper

Nhưng không liên quan đến điều đó, câu trả lời này không giải thích được liệu và tại sao, thay vì ContentPresenter, ContentControlkhông thể sử dụng tốt như vậy ControlTemplateđể hiển thị nội dung của Button. Như vậy, nó không trả lời câu hỏi.
HOẶC Mapper
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.