從類的層次級別,結合例子,說明ContentControl和ContentPresenter的作用和關系。同時,也對比了ItemsControl和ItemsPresenter,更有利於從WPF整體的類結構來對比理解。
我們先看類層次
ContentControl繼承自Control,而ContentPresenter繼承自FrameworkElement。所以最根本的認識:ContentControl是一個控件,而ContentPresenter直接來自FrameworkElement(Control直接繼承自FrameworkElement)。同理,ItemsControl繼承自Control,而ItemsPresenter繼承自FrameworkElement。
ItemsControl是一個控件,它知道如何顯示數據集合(Collection of data),再其內部包含有ItemsPresenter。比較常見的來自ItemsControl的控件,比如ComboBox,ContextMenu,ListBox,DataGrid,ListView等。
ContentControl是一個控件,它知道如何顯示單個數據(non-collection data),在其內部包含有ContentPresenter。比較常見的來自ContentControl的控件,比如Button,Label等。
結合例子深入細節
ContentPresenter元素被用於ContentControl的template的內部,我們可以把ContentPresenter放置在我們需要的特定的地方。比如,一個Button的Content為“MyButton”,我們為這個Button重寫一個ControlTemplate,如果我們不放置ContentPresenter,“MyButton”這個詞就不會被顯示;如果我們在ControlTemplate的某個位置放置的ContentPresenter,“MyButton”就會顯示的相應的位置。
所以一個ContentPresenter可以看成是下面邏輯的等效:
<ContentPresenter Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}" ContentTemplateSelector="{TemplateBinding ContentTemplateSelector}" />
ContentPresenter隱式假設以上這些就是大多數人默認需要的內容(事實也確實如此),所以以下更為簡潔的等效寫法:
<ContentPresenter/>
但是,當我們不想用ContentPresenter默認的行為的時候,我們可以自己定義,比如:
<ContentPresenter Content="{TemplateBinding Height}"/>
這個時候,ContentPresenter的位置,就會顯示高度,如“320”,而不是“MyButton”。
結論
總的來說,ContentControl是一個擁有ControlTemplate的控件,用來顯示單個非集合數據;ContentPreseter用來指定content在ContentControl(ControlTemplate)中的位置。