(注:本文是《剖析WPF模板機制的內(nèi)部實現(xiàn)》系列文章的第二篇,查看上一篇文章點這里)
2. ControlTemplate ControlTemplate類是最簡單的FrameworkTemplate子類,而最常見的ControlTemplate類型變量是Control.Template屬性。 上一篇我們提到,F(xiàn)rameworkElement子類要想生成自己的visual tree,就必須自定義一個模板給TemplateInternal屬性。一個FrameworkElement子類元素的visual tree完全取決其提供給TemplateInternal屬性的實際模板。 我們將看到,作為FrameworkElement的子類,Control除了覆寫了TemplateInternal和TemplateCache屬性,還新定義了一個ControlTemplate類型的Template屬性: //*****************Control******************** 可以看到,覆寫后,TemplateInternal屬性返回的就是Template,而Template屬性返回的是_templateCache字段,這個字段又是TemplateCache屬性的支撐字段,而TemplateCache屬性只在StyleHelper.UpdateTemplateCache()方法里被修改過。這個方法的代碼如下: //*****************StyleHelper********************* internal static void UpdateTemplateCache( FrameworkElement fe, FrameworkTemplate oldTemplate, FrameworkTemplate newTemplate, DependencyProperty templateProperty) { DependencyObject d = fe;// Update the template cache fe.TemplateCache = newTemplate; // Do template property invalidations. Note that some of the invalidations may be callouts // that could turn around and query the template property on this node. Hence it is essential // to update the template cache before we do this operation. StyleHelper.DoTemplateInvalidations(fe, oldTemplate); // Now look for triggers that might want their EnterActions or ExitActions // to run immediately. StyleHelper.ExecuteOnApplyEnterExitActions(fe, null, newTemplate); }
這意味著每次更新Control.Template都會相應(yīng)更新_templateCache,從而FrameworkElement.ApplyTemplate()讀到的TemplateInternal的值也就是Control.Template的值。就這樣,Control類在無法覆寫ApplyTemplate()方法的情況下,實現(xiàn)了模板應(yīng)用的多態(tài)性。值得一提的是,我們后面將看到,這種模式已經(jīng)成了FrameworkElement子類對虛屬性TemplateInternal實現(xiàn)多態(tài)性的固定模式。另外,前面我們提到只有4個FrameworkElement的子類覆寫了TemplateInternal屬性:Control、ContentPresenter、ItemsPresenter、Page,因此可以期望在后面三種類里面也能找到類似的TemplateInternal多態(tài)性實現(xiàn)機制。 其他ControlTemplate類型的變量還有Page.Template,DataGrid.RowValidationErrorTemplate等。它們的模板機制與Control.Template大同小異,這里就不一一贅述了。下一篇文章我們將討論ItemsPanelTemplate類。
|
|