日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

WPF源代碼分析系列一:剖析WPF模板機制的內(nèi)部實現(xiàn)(二)

 小仙女本仙人 2021-03-11

(注:本文是《剖析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除了覆寫了TemplateInternalTemplateCache屬性,還新定義了一個ControlTemplate類型的Template屬性:

//*****************Control********************

public static readonly DependencyProperty TemplateProperty = DependencyProperty.Register( "Template", typeof(ControlTemplate), typeof(Control), new FrameworkPropertyMetadata( (ControlTemplate) null, // default value FrameworkPropertyMetadataOptions.AffectsMeasure, new PropertyChangedCallback(OnTemplateChanged))); /// <summary> /// Template Property /// </summary> public ControlTemplate Template { get { return _templateCache; } set { SetValue(TemplateProperty, value); } } // Internal Helper so the FrameworkElement could see this property internal override FrameworkTemplate TemplateInternal { get { return Template; } } // Internal Helper so the FrameworkElement could see the template cache internal override FrameworkTemplate TemplateCache { get { return _templateCache; } set { _templateCache = (ControlTemplate) value; } } // Internal helper so FrameworkElement could see call the template changed virtual internal override void OnTemplateChangedInternal(FrameworkTemplate oldTemplate, FrameworkTemplate newTemplate) { OnTemplateChanged((ControlTemplate)oldTemplate, (ControlTemplate)newTemplate); } // Property invalidation callback invoked when TemplateProperty is invalidated private static void OnTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { Control c = (Control) d; StyleHelper.UpdateTemplateCache(c, (FrameworkTemplate) e.OldValue, (FrameworkTemplate) e.NewValue, TemplateProperty); }

可以看到,覆寫后,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類。

 

 

 

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多