Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / System / Windows / Controls / ContentPresenter.cs / 1544695 / ContentPresenter.cs
//---------------------------------------------------------------------------- // //// Copyright (C) Microsoft Corporation. All rights reserved. // // // Description: ContentPresenter class // // Specs: http://avalon/connecteddata/M5%20General%20Docs/Data%20Styling.mht // //--------------------------------------------------------------------------- using System; using System.Diagnostics; using System.ComponentModel; using System.Reflection; using System.Xml; using System.Windows.Threading; using System.Windows.Shapes; using System.Windows.Media; using System.Windows.Data; using System.Windows.Markup; using MS.Internal; using MS.Internal.Data; using MS.Internal.KnownBoxes; using System.Windows.Documents; using MS.Utility; using MS.Internal.PresentationFramework; using System.Collections.Specialized; namespace System.Windows.Controls { ////// ContentPresenter is used within the template of a content control to denote the /// place in the control's visual tree (control template) where the content /// is to be added. /// [Localizability(LocalizationCategory.None, Readability = Readability.Unreadable)] public class ContentPresenter : FrameworkElement { //----------------------------------------------------- // // Constructors // //----------------------------------------------------- static ContentPresenter() { DataTemplate template; FrameworkElementFactory text; Binding binding; // Default template for strings when hosted in ContentPresener with RecognizesAccessKey=true template = new DataTemplate(); text = CreateAccessTextFactory(); text.SetValue(AccessText.TextProperty, new TemplateBindingExtension(ContentProperty)); template.VisualTree = text; template.Seal(); s_AccessTextTemplate = template; // Default template for strings template = new DataTemplate(); text = CreateTextBlockFactory(); text.SetValue(TextBlock.TextProperty, new TemplateBindingExtension(ContentProperty)); template.VisualTree = text; template.Seal(); s_StringTemplate = template; // Default template for XmlNodes template = new DataTemplate(); text = CreateTextBlockFactory(); binding = new Binding(); binding.XPath = "."; text.SetBinding(TextBlock.TextProperty, binding); template.VisualTree = text; template.Seal(); s_XmlNodeTemplate = template; // Default template for UIElements template = new UseContentTemplate(); template.Seal(); s_UIElementTemplate = template; // Default template for everything else template = new DefaultTemplate(); template.Seal(); s_DefaultTemplate = template; // Default template selector s_DefaultTemplateSelector = new DefaultSelector(); } ////// Default constructor /// ////// Automatic determination of current Dispatcher. Use alternative constructor /// that accepts a Dispatcher for best performance. /// public ContentPresenter() : base() { Initialize(); } void Initialize() { // Initialize the _templateCache to the default value for TemplateProperty. // If the default value is non-null then wire it to the current instance. PropertyMetadata metadata = TemplateProperty.GetMetadata(DependencyObjectType); DataTemplate defaultValue = (DataTemplate) metadata.DefaultValue; if (defaultValue != null) { OnTemplateChanged(this, new DependencyPropertyChangedEventArgs(TemplateProperty, metadata, null, defaultValue)); } DataContext = null; // this presents a uniform view: CP always has local DC } //------------------------------------------------------ // // Public Properties // //----------------------------------------------------- ////// The DependencyProperty for the RecognizesAccessKey property. /// Flags: None /// Default Value: false /// [CommonDependencyProperty] public static readonly DependencyProperty RecognizesAccessKeyProperty = DependencyProperty.Register( "RecognizesAccessKey", typeof(bool), typeof(ContentPresenter), new FrameworkPropertyMetadata(BooleanBoxes.FalseBox)); ////// Determine if ContentPresenter should use AccessText in its style /// public bool RecognizesAccessKey { get { return (bool) GetValue(RecognizesAccessKeyProperty); } set { SetValue(RecognizesAccessKeyProperty, BooleanBoxes.Box(value)); } } ////// The DependencyProperty for the Content property. /// Flags: None /// Default Value: null /// // Any change in Content properties affectes layout measurement since // a new template may be used. On measurement, // ApplyTemplate will be invoked leading to possible application // of a new template. [CommonDependencyProperty] public static readonly DependencyProperty ContentProperty = ContentControl.ContentProperty.AddOwner( typeof(ContentPresenter), new FrameworkPropertyMetadata( (object)null, FrameworkPropertyMetadataOptions.AffectsMeasure, new PropertyChangedCallback(OnContentChanged))); ////// Content is the data used to generate the child elements of this control. /// public object Content { get { return GetValue(ContentControl.ContentProperty); } set { SetValue(ContentControl.ContentProperty, value); } } ////// Called when ContentProperty is invalidated on "d." /// private static void OnContentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ContentPresenter ctrl = (ContentPresenter)d; // if we're already marked to reselect the template, there's nothing more to do if (!ctrl._templateIsCurrent) return; bool mismatch; if (e.NewValue == BindingExpressionBase.DisconnectedItem) { mismatch = false; // do not change templates when disconnecting } else if (ctrl.ContentTemplate != null) { mismatch = false; // explicit template - matches by fiat } else if (ctrl.ContentTemplateSelector != null) { mismatch = true; // template selector - always re-select } else if (ctrl.Template == UIElementContentTemplate) { mismatch = true; // direct template - always re-apply ctrl.Template = null; // and release the old content so it can be re-used elsewhere } else if (ctrl.Template == DefaultContentTemplate) { mismatch = true; // default template - always re-apply } else { // implicit template - matches if data types agree Type type; // unused object oldDataType = DataTypeForItem(e.OldValue, ctrl, out type); object newDataType = DataTypeForItem(e.NewValue, ctrl, out type); mismatch = (oldDataType != newDataType); // but mismatch if we're displaying strings via a default template // and the presence of an AccessKey changes if (!mismatch && ctrl.RecognizesAccessKey && Object.ReferenceEquals(typeof(String), newDataType) && ctrl.IsUsingDefaultStringTemplate) { String oldString = (String)e.OldValue; String newString = (String)e.NewValue; bool oldHasAccessKey = (oldString.IndexOf(AccessText.AccessKeyMarker) > -1); bool newHasAccessKey = (newString.IndexOf(AccessText.AccessKeyMarker) > -1); if (oldHasAccessKey != newHasAccessKey) { mismatch = true; } } } // if the content and (old) template don't match, reselect the template if (mismatch) { ctrl._templateIsCurrent = false; } // keep the DataContext in [....] with Content if (ctrl._templateIsCurrent && ctrl.Template != UIElementContentTemplate) { ctrl.DataContext = e.NewValue; } } ////// The DependencyProperty for the ContentTemplate property. /// Flags: None /// Default Value: null /// [CommonDependencyProperty] public static readonly DependencyProperty ContentTemplateProperty = ContentControl.ContentTemplateProperty.AddOwner( typeof(ContentPresenter), new FrameworkPropertyMetadata( (DataTemplate)null, FrameworkPropertyMetadataOptions.AffectsMeasure, new PropertyChangedCallback(OnContentTemplateChanged))); ////// ContentTemplate is the template used to display the content of the control. /// public DataTemplate ContentTemplate { get { return (DataTemplate) GetValue(ContentControl.ContentTemplateProperty); } set { SetValue(ContentControl.ContentTemplateProperty, value); } } ////// Called when ContentTemplateProperty is invalidated on "d." /// private static void OnContentTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ContentPresenter ctrl = (ContentPresenter)d; ctrl._templateIsCurrent = false; ctrl.OnContentTemplateChanged((DataTemplate) e.OldValue, (DataTemplate) e.NewValue); } ////// This method is invoked when the ContentTemplate property changes. /// /// The old value of the ContentTemplate property. /// The new value of the ContentTemplate property. protected virtual void OnContentTemplateChanged(DataTemplate oldContentTemplate, DataTemplate newContentTemplate) { Helper.CheckTemplateAndTemplateSelector("Content", ContentTemplateProperty, ContentTemplateSelectorProperty, this); // if ContentTemplate is really changing, remove the old template this.Template = null; } ////// The DependencyProperty for the ContentTemplateSelector property. /// Flags: None /// Default Value: null /// [CommonDependencyProperty] public static readonly DependencyProperty ContentTemplateSelectorProperty = ContentControl.ContentTemplateSelectorProperty.AddOwner( typeof(ContentPresenter), new FrameworkPropertyMetadata( (DataTemplateSelector)null, FrameworkPropertyMetadataOptions.AffectsMeasure, new PropertyChangedCallback(OnContentTemplateSelectorChanged))); ////// ContentTemplateSelector allows the application writer to provide custom logic /// for choosing the template used to display the content of the control. /// ////// This property is ignored if public DataTemplateSelector ContentTemplateSelector { get { return (DataTemplateSelector) GetValue(ContentControl.ContentTemplateSelectorProperty); } set { SetValue(ContentControl.ContentTemplateSelectorProperty, value); } } ///is set. /// /// This method is used by TypeDescriptor to determine if this property should /// be serialized. /// [EditorBrowsable(EditorBrowsableState.Never)] public bool ShouldSerializeContentTemplateSelector() { return false; } ////// Called when ContentTemplateSelectorProperty is invalidated on "d." /// private static void OnContentTemplateSelectorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ContentPresenter ctrl = (ContentPresenter) d; ctrl._templateIsCurrent = false; ctrl.OnContentTemplateSelectorChanged((DataTemplateSelector) e.OldValue, (DataTemplateSelector) e.NewValue); } ////// This method is invoked when the ContentTemplateSelector property changes. /// /// The old value of the ContentTemplateSelector property. /// The new value of the ContentTemplateSelector property. protected virtual void OnContentTemplateSelectorChanged(DataTemplateSelector oldContentTemplateSelector, DataTemplateSelector newContentTemplateSelector) { Helper.CheckTemplateAndTemplateSelector("Content", ContentTemplateProperty, ContentTemplateSelectorProperty, this); // if ContentTemplateSelector is really changing (and in use), remove the old template this.Template = null; } ////// The DependencyProperty for the ContentStringFormat property. /// Flags: None /// Default Value: null /// [CommonDependencyProperty] public static readonly DependencyProperty ContentStringFormatProperty = DependencyProperty.Register( "ContentStringFormat", typeof(String), typeof(ContentPresenter), new FrameworkPropertyMetadata( (String) null, new PropertyChangedCallback(OnContentStringFormatChanged))); ////// ContentStringFormat is the format used to display the content of /// the control as a string. This arises only when no template is /// available. /// [Bindable(true), CustomCategory("Content")] public String ContentStringFormat { get { return (String) GetValue(ContentStringFormatProperty); } set { SetValue(ContentStringFormatProperty, value); } } ////// Called when ContentStringFormatProperty is invalidated on "d." /// private static void OnContentStringFormatChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ContentPresenter ctrl = (ContentPresenter)d; ctrl.OnContentStringFormatChanged((String) e.OldValue, (String) e.NewValue); } ////// This method is invoked when the ContentStringFormat property changes. /// /// The old value of the ContentStringFormat property. /// The new value of the ContentStringFormat property. protected virtual void OnContentStringFormatChanged(String oldContentStringFormat, String newContentStringFormat) { // force on-demand regeneration of the formatting templates for XML and String content XMLFormattingTemplateField.ClearValue(this); StringFormattingTemplateField.ClearValue(this); AccessTextFormattingTemplateField.ClearValue(this); } ////// The DependencyProperty for the ContentSource property. /// Flags: None /// Default Value: Content /// [CommonDependencyProperty] public static readonly DependencyProperty ContentSourceProperty = DependencyProperty.Register( "ContentSource", typeof(string), typeof(ContentPresenter), new FrameworkPropertyMetadata("Content")); ////// ContentSource is the base name to use during automatic aliasing. /// When a template contains a ContentPresenter with ContentSource="Abc", /// its Content, ContentTemplate, ContentTemplateSelector, and ContentStringFormat /// properties are automatically aliased to Abc, AbcTemplate, AbcTemplateSelector, /// and AbcStringFormat respectively. The two most useful values for /// ContentSource are "Content" and "Header"; the default is "Content". /// ////// This property only makes sense in a template. It should not be set on /// an actual ContentPresenter; there will be no effect. /// public string ContentSource { get { return GetValue(ContentSourceProperty) as string; } set { SetValue(ContentSourceProperty, value); } } //------------------------------------------------------ // // Protected Methods // //------------------------------------------------------ ////// Called when the Template's tree is about to be generated /// internal override void OnPreApplyTemplate() { base.OnPreApplyTemplate(); // If we're inflating our visual tree but our TemplatedParent is null, // we might have been removed from the visual tree but not have had // our ContentProperty invalidated. This would mean that when we go // to reparent our content, we'll be looking at a stale cache. Make // sure to invalidate the Content property in this case. if (TemplatedParent == null) { // call GetValueCore to get this value from its TemplatedParent InvalidateProperty(ContentProperty); } // If the ContentPresenter is using "default expansion", the result // depends on the Language property. There is no notification when it // changes (i.e. no virtual OnLanguageChanged method), but it is marked // as AffectsMeasure, so the CP will be re-measured and will call into // OnPreApplyTemplate. At this point, if Language has changed (and if // we're actually using it), invalidate the template. This will cause // DoDefaultExpansion to run again with the new language. if (_language != null && _language != this.Language) { _templateIsCurrent = false; } if (!_templateIsCurrent) { EnsureTemplate(); _templateIsCurrent = true; } } ////// Updates DesiredSize of the ContentPresenter. Called by parent UIElement. This is the first pass of layout. /// ////// ContentPresenter determines a desired size it needs from the child's sizing properties, margin, and requested size. /// /// Constraint size is an "upper limit" that the return value should not exceed. ///The ContentPresenter's desired size. protected override Size MeasureOverride(Size constraint) { return Helper.MeasureElementWithSingleChild(this, constraint); } ////// ContentPresenter computes the position of its single child inside child's Margin and calls Arrange /// on the child. /// /// Size the ContentPresenter will assume. protected override Size ArrangeOverride(Size arrangeSize) { return Helper.ArrangeElementWithSingleChild(this, arrangeSize); } ////// Return the template to use. This may depend on the Content, or /// other properties. /// ////// The base class implements the following rules: /// (a) If ContentTemplate is set, use it. /// (b) If ContentTemplateSelector is set, call its /// SelectTemplate method. If the result is not null, use it. /// (c) Look for a DataTemplate whose DataType matches the /// Content among the resources known to the ContentPresenter /// (including application, theme, and system resources). /// If one is found, use it. /// (d) If the type of Content is "common", use a standard template. /// The common types are String, XmlNode, UIElement. /// (e) Otherwise, use a default template that essentially converts /// Content to a string and displays it in a TextBlock. /// Derived classes can override these rules and implement their own. /// protected virtual DataTemplate ChooseTemplate() { DataTemplate template = null; object content = Content; // ContentTemplate has first stab template = ContentTemplate; // no ContentTemplate set, try ContentTemplateSelector if (template == null) { if (ContentTemplateSelector != null) { template = ContentTemplateSelector.SelectTemplate(content, this); } } // if that failed, try the default TemplateSelector if (template == null) { template = DefaultTemplateSelector.SelectTemplate(content, this); } return template; } //----------------------------------------------------- // // Internal properties // //------------------------------------------------------ internal static DataTemplate AccessTextContentTemplate { get { return s_AccessTextTemplate; } } internal static DataTemplate StringContentTemplate { get { return s_StringTemplate; } } // 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 = (DataTemplate)value; } } internal bool TemplateIsCurrent { get { return _templateIsCurrent; } } //----------------------------------------------------- // // Internal methods // //----------------------------------------------------- ////// Prepare to display the item. /// internal void PrepareContentPresenter(object item, DataTemplate itemTemplate, DataTemplateSelector itemTemplateSelector, string stringFormat) { if (item != this) { // copy templates from parent ItemsControl if (_contentIsItem || !HasNonDefaultValue(ContentProperty)) { Content = item; _contentIsItem = true; } if (itemTemplate != null) SetValue(ContentTemplateProperty, itemTemplate); if (itemTemplateSelector != null) SetValue(ContentTemplateSelectorProperty, itemTemplateSelector); if (stringFormat != null) SetValue(ContentStringFormatProperty, stringFormat); } } ////// Undo the effect of PrepareContentPresenter. /// internal void ClearContentPresenter(object item) { if (item != this) { if (_contentIsItem) { Content = BindingExpressionBase.DisconnectedItem; } } } internal static object DataTypeForItem(object item, DependencyObject target, out Type type) { if (item == null) { type = null; return null; } object dataType; type = item.GetType(); if (AssemblyHelper.IsXElement(item)) { dataType = AssemblyHelper.GetXElementTagName(item); type = null; } else if (AssemblyHelper.IsXmlNode(item)) { dataType = GetXmlTagName(item, target); type = null; } else if (type == typeof(Object)) { dataType = null; // don't search for Object - perf } else { dataType = type; } return dataType; } //----------------------------------------------------- // // Private properties // //------------------------------------------------------ static DataTemplate XmlNodeContentTemplate { get { return s_XmlNodeTemplate; } } static DataTemplate UIElementContentTemplate { get { return s_UIElementTemplate; } } static DataTemplate DefaultContentTemplate { get { return s_DefaultTemplate; } } static DefaultSelector DefaultTemplateSelector { get { return s_DefaultTemplateSelector; } } DataTemplate FormattingAccessTextContentTemplate { get { DataTemplate template = AccessTextFormattingTemplateField.GetValue(this); if (template == null) { Binding binding = new Binding(); binding.StringFormat = ContentStringFormat; FrameworkElementFactory text = CreateAccessTextFactory(); text.SetBinding(AccessText.TextProperty, binding); template = new DataTemplate(); template.VisualTree = text; template.Seal(); AccessTextFormattingTemplateField.SetValue(this, template); } return template; } } DataTemplate FormattingStringContentTemplate { get { DataTemplate template = StringFormattingTemplateField.GetValue(this); if (template == null) { Binding binding = new Binding(); binding.StringFormat = ContentStringFormat; FrameworkElementFactory text = CreateTextBlockFactory(); text.SetBinding(TextBlock.TextProperty, binding); template = new DataTemplate(); template.VisualTree = text; template.Seal(); StringFormattingTemplateField.SetValue(this, template); } return template; } } DataTemplate FormattingXmlNodeContentTemplate { get { DataTemplate template = XMLFormattingTemplateField.GetValue(this); if (template == null) { Binding binding = new Binding(); binding.XPath = "."; binding.StringFormat = ContentStringFormat; FrameworkElementFactory text = CreateTextBlockFactory(); text.SetBinding(TextBlock.TextProperty, binding); template = new DataTemplate(); template.VisualTree = text; template.Seal(); XMLFormattingTemplateField.SetValue(this, template); } return template; } } ////// TemplateProperty /// internal static readonly DependencyProperty TemplateProperty = DependencyProperty.Register( "Template", typeof(DataTemplate), typeof(ContentPresenter), new FrameworkPropertyMetadata( (DataTemplate) null, // default value FrameworkPropertyMetadataOptions.AffectsMeasure, new PropertyChangedCallback(OnTemplateChanged))); ////// Template Property /// private DataTemplate Template { get { return _templateCache; } set { SetValue(TemplateProperty, value); } } // Internal helper so FrameworkElement could see call the template changed virtual internal override void OnTemplateChangedInternal(FrameworkTemplate oldTemplate, FrameworkTemplate newTemplate) { OnTemplateChanged((DataTemplate)oldTemplate, (DataTemplate)newTemplate); } // Property invalidation callback invoked when TemplateProperty is invalidated private static void OnTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ContentPresenter c = (ContentPresenter) d; StyleHelper.UpdateTemplateCache(c, (FrameworkTemplate) e.OldValue, (FrameworkTemplate) e.NewValue, TemplateProperty); } ////// Template has changed /// ////// When a Template changes, the VisualTree is removed. The new Template's /// VisualTree will be created when ApplyTemplate is called /// /// The old Template /// The new Template protected virtual void OnTemplateChanged(DataTemplate oldTemplate, DataTemplate newTemplate) { } //----------------------------------------------------- // // Private methods // //------------------------------------------------------ private void EnsureTemplate() { DataTemplate oldTemplate = Template; DataTemplate newTemplate = null; for (_templateIsCurrent = false; !_templateIsCurrent; ) { // normally this loop will execute exactly once. The only exception // is when setting the DataContext causes the ContentTemplate or // ContentTemplateSelector to change, presumably because they are // themselves data-bound (see bug 128119). In that case, we need // to call ChooseTemplate again, to pick up the new template. // We detect this case because _templateIsCurrent is reset to false // in OnContentTemplate[Selector]Changed, causing a second iteration // of the loop. _templateIsCurrent = true; newTemplate = ChooseTemplate(); // if the template is changing, it's important that the code that cleans // up the old template runs while the CP's DataContext is still set to // the old Content. The way to get this effect is: // a. change the template to null // b. change the data context // c. change the template to the new value if (oldTemplate != newTemplate) { Template = null; } if (newTemplate != UIElementContentTemplate) { // set data context to the content, so that the template can bind to // properties of the content. this.DataContext = Content; } else { // If we're using the content directly, clear the data context. // The content expects to inherit. this.ClearValue(DataContextProperty); } } Template = newTemplate; // if the template didn't change, we still need to force the content for the template to be regenerated; // so call StyleHelper's DoTemplateInvalidations directly if (oldTemplate == newTemplate) { StyleHelper.DoTemplateInvalidations(this, oldTemplate); } } // Select a template for string content DataTemplate SelectTemplateForString(string s) { DataTemplate template; string format = ContentStringFormat; if (this.RecognizesAccessKey && s.IndexOf(AccessText.AccessKeyMarker) > -1) { template = (String.IsNullOrEmpty(format)) ? AccessTextContentTemplate : FormattingAccessTextContentTemplate; } else { template = (String.IsNullOrEmpty(format)) ? StringContentTemplate : FormattingStringContentTemplate; } return template; } // return true if the template was chosen by SelectTemplateForString bool IsUsingDefaultStringTemplate { get { if (Template == StringContentTemplate || Template == AccessTextContentTemplate) { return true; } DataTemplate template; template = StringFormattingTemplateField.GetValue(this); if (template != null && template == Template) { return true; } template = AccessTextFormattingTemplateField.GetValue(this); if (template != null && template == Template) { return true; } return false; } } // Select a template for XML content DataTemplate SelectTemplateForXML() { return (String.IsNullOrEmpty(ContentStringFormat)) ? XmlNodeContentTemplate : FormattingXmlNodeContentTemplate; } // ContentPresenter often has occasion to display text. The TextBlock it uses // should get the values for various text-related properties (foreground, fonts, // decoration, trimming) from the governing ContentControl. The following // two methods accomplish this - first for the case where the TextBlock appears // in a true template, then for the case where the TextBlock is created on // demand via BuildVisualTree. // Create a FEF for a AccessText, to be used in a default template internal static FrameworkElementFactory CreateAccessTextFactory() { FrameworkElementFactory text = new FrameworkElementFactory(typeof(AccessText)); return text; } // Create a FEF for a TextBlock, to be used in a default template internal static FrameworkElementFactory CreateTextBlockFactory() { FrameworkElementFactory text = new FrameworkElementFactory(typeof(TextBlock)); return text; } // Create a TextBlock, to be used in a default "template" (via BuildVisualTree) static TextBlock CreateTextBlock(ContentPresenter container) { TextBlock text = new TextBlock(); return text; } // Cache the Language property when it's used by DoDefaultExpansion, so // that we can detect changes. (This could also be done by a virtual // OnLanguageChanged method, if FrameworkElement ever defines one.) private void CacheLanguage(XmlLanguage language) { _language = language; } // // This property // 1. Finds the correct initial size for the _effectiveValues store on the current DependencyObject // 2. This is a performance optimization // internal override int EffectiveValuesInitialSize { get { return 28; } } // separate function to avoid loading System.Xml until we have a good reason [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] private static string GetXmlTagName(object item, DependencyObject target) { System.Xml.XmlNode node = (System.Xml.XmlNode)item; XmlNamespaceManager namespaceManager = GetXmlNamespaceManager(target); if (namespaceManager != null) { string prefix = namespaceManager.LookupPrefix(node.NamespaceURI); if (prefix != string.Empty) return string.Concat(prefix, ":", node.LocalName); } return node.Name; } // find the appropriate namespace manager for the given element private static XmlNamespaceManager GetXmlNamespaceManager(DependencyObject target) { XmlNamespaceManager nsmgr = Binding.GetXmlNamespaceManager(target); if (nsmgr == null) { XmlDataProvider xdp = Helper.XmlDataProviderForElement(target); nsmgr = (xdp != null) ? xdp.XmlNamespaceManager : null; } return nsmgr; } //------------------------------------------------------ // // Private nested classes // //----------------------------------------------------- // Template for displaying UIElements - use the UIElement itself private class UseContentTemplate : DataTemplate { public UseContentTemplate() { // We need to preserve the treeState cache on a container node // even after all its logical children have been added. This is so the // construction of the template visual tree nodes can consume the cache. // This member helps us know whether we should retain the cache for // special scenarios when the visual tree is being built via BuildVisualTree CanBuildVisualTree = true; } internal override bool BuildVisualTree(FrameworkElement container) { object content = ((ContentPresenter)container).Content; UIElement e = content as UIElement; if (e == null) { TypeConverter tc = TypeDescriptor.GetConverter(content.GetType()); Debug.Assert(tc.CanConvertTo(typeof(UIElement))); e = (UIElement) tc.ConvertTo(content, typeof(UIElement)); } StyleHelper.AddCustomTemplateRoot( container, e ); return true; } } // template for displaying content when all else fails private class DefaultTemplate : DataTemplate { public DefaultTemplate() { // We need to preserve the treeState cache on a container node // even after all its logical children have been added. This is so the // construction of the template visual tree nodes can consume the cache. // This member helps us know whether we should retain the cache for // special scenarios when the visual tree is being built via BuildVisualTree CanBuildVisualTree = true; } //[CodeAnalysis("AptcaMethodsShouldOnlyCallAptcaMethods")] //Tracking Bug: 29647 internal override bool BuildVisualTree(FrameworkElement container) { bool tracingEnabled = EventTrace.IsEnabled(EventTrace.Keyword.KeywordGeneral, EventTrace.Level.Info); if (tracingEnabled) { EventTrace.EventProvider.TraceEvent(EventTrace.Event.WClientStringBegin, EventTrace.Keyword.KeywordGeneral, EventTrace.Level.Info, "ContentPresenter.BuildVisualTree"); } try { ContentPresenter cp = (ContentPresenter)container; Visual result = DefaultExpansion(cp.Content, cp); return (result != null); } finally { if (tracingEnabled) { EventTrace.EventProvider.TraceEvent(EventTrace.Event.WClientStringEnd, EventTrace.Keyword.KeywordGeneral, EventTrace.Level.Info, String.Format(System.Globalization.CultureInfo.InvariantCulture, "ContentPresenter.BuildVisualTree for CP {0}", container.GetHashCode())); } } } private UIElement DefaultExpansion(object content, ContentPresenter container) { if (content == null) return null; TextBlock textBlock = CreateTextBlock(container); textBlock.IsContentPresenterContainer = true; // this is done so that the TextBlock does not steal away the logical child if( container != null ) { StyleHelper.AddCustomTemplateRoot( container, textBlock, false, // Do not need to check for existing visual parent since we just created it true); // set treeState cache on the Text instance created } DoDefaultExpansion(textBlock, content, container); return textBlock; } private void DoDefaultExpansion(TextBlock textBlock, object content, ContentPresenter container) { Debug.Assert(!(content is String) && !(content is UIElement)); // these are handled by different templates Inline inline; if ((inline = content as Inline) != null) { textBlock.Inlines.Add(inline); } else { bool succeeded = false; string stringFormat; Type t = content.GetType(); TypeConverter tc = TypeDescriptor.GetConverter(t); XmlLanguage language = container.Language; System.Globalization.CultureInfo culture = language.GetSpecificCulture(); container.CacheLanguage(language); if ((stringFormat = container.ContentStringFormat) != null) { try { stringFormat = Helper.GetEffectiveStringFormat(stringFormat); textBlock.Text = String.Format(culture, stringFormat, content); succeeded = true; } catch (FormatException) { } } if (!succeeded) { if ((tc = TypeDescriptor.GetConverter(content.GetType())) != null && (tc.CanConvertTo(typeof(String)))) { textBlock.Text = (string)tc.ConvertTo(null, culture, content, typeof(string)); } else { Debug.Assert(!(tc != null && tc.CanConvertTo(typeof(UIElement)))); // this is handled by a different template textBlock.Text = String.Format(culture, "{0}", content); } } } } } private class DefaultSelector : DataTemplateSelector { ////// Override this method to return an app specific /// The data content /// The container in which the content is to be displayed ///. /// a app specific template to apply. public override DataTemplate SelectTemplate(object item, DependencyObject container) { DataTemplate template = null; // Lookup template for typeof(Content) in resource dictionaries. if (item != null) { template = (DataTemplate)FrameworkElement.FindTemplateResourceInternal(container, item, typeof(DataTemplate)); } // default templates for well known types: if (template == null) { TypeConverter tc = null; string s; if ((s = item as string) != null) template = ((ContentPresenter)container).SelectTemplateForString(s); else if (item is UIElement) template = UIElementContentTemplate; else if (AssemblyHelper.IsXmlNode(item)) template = ((ContentPresenter)container).SelectTemplateForXML(); else if (item is Inline) template = DefaultContentTemplate; else if (item != null && (tc = TypeDescriptor.GetConverter(item.GetType())) != null && tc.CanConvertTo(typeof(UIElement))) template = UIElementContentTemplate; else template = DefaultContentTemplate; } return template; } } //------------------------------------------------------ // // Private Fields // //----------------------------------------------------- private DataTemplate _templateCache; private bool _templateIsCurrent; private bool _contentIsItem; private XmlLanguage _language; private static DataTemplate s_AccessTextTemplate; private static DataTemplate s_StringTemplate; private static DataTemplate s_XmlNodeTemplate; private static DataTemplate s_UIElementTemplate; private static DataTemplate s_DefaultTemplate; private static DefaultSelector s_DefaultTemplateSelector; private static readonly UncommonFieldXMLFormattingTemplateField = new UncommonField (); private static readonly UncommonField StringFormattingTemplateField = new UncommonField (); private static readonly UncommonField AccessTextFormattingTemplateField = new UncommonField (); } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- BinaryObjectInfo.cs
- InfoCardRSAPKCS1KeyExchangeDeformatter.cs
- TransformerInfoCollection.cs
- TreeViewImageKeyConverter.cs
- FrameworkContentElement.cs
- EntityStoreSchemaGenerator.cs
- XmlFormatExtensionAttribute.cs
- PhysicalOps.cs
- Inline.cs
- Thumb.cs
- Item.cs
- FloatSumAggregationOperator.cs
- DirectionalLight.cs
- XPathConvert.cs
- HostingEnvironment.cs
- TextContainerChangedEventArgs.cs
- NativeObjectSecurity.cs
- WorkflowRuntimeService.cs
- StylusPointPropertyInfoDefaults.cs
- DesigntimeLicenseContextSerializer.cs
- TextPointer.cs
- XmlSchemaInfo.cs
- EventManager.cs
- WinEventWrap.cs
- RSAPKCS1SignatureDeformatter.cs
- XmlElementCollection.cs
- Socket.cs
- CodeArrayCreateExpression.cs
- Converter.cs
- Pointer.cs
- LogStream.cs
- ActiveXHost.cs
- GifBitmapDecoder.cs
- CompilerResults.cs
- DropAnimation.xaml.cs
- UnsafeNetInfoNativeMethods.cs
- UndirectedGraph.cs
- Int32RectConverter.cs
- RandomNumberGenerator.cs
- HorizontalAlignConverter.cs
- CommonXSendMessage.cs
- DynamicResourceExtension.cs
- UInt32.cs
- KernelTypeValidation.cs
- Compress.cs
- ByteStreamMessage.cs
- EntityClassGenerator.cs
- PointAnimationClockResource.cs
- SendParametersContent.cs
- RecordBuilder.cs
- GlyphRunDrawing.cs
- PolyBezierSegmentFigureLogic.cs
- UnsafeNativeMethodsMilCoreApi.cs
- MetadataUtilsSmi.cs
- WeakReadOnlyCollection.cs
- ExpressionDumper.cs
- securestring.cs
- CompoundFileReference.cs
- ImageSourceValueSerializer.cs
- AddressHeaderCollection.cs
- Group.cs
- StylusLogic.cs
- BinaryObjectReader.cs
- TimelineGroup.cs
- ExtenderProviderService.cs
- CategoryAttribute.cs
- TreeNodeCollectionEditorDialog.cs
- DoubleCollectionConverter.cs
- WebConvert.cs
- GAC.cs
- MsmqProcessProtocolHandler.cs
- DataPagerFieldCollection.cs
- ClientData.cs
- XmlAnyAttributeAttribute.cs
- TypeDelegator.cs
- VirtualizingPanel.cs
- CompilerScopeManager.cs
- ListBox.cs
- ExtensionFile.cs
- XmlElementCollection.cs
- UserNameSecurityTokenParameters.cs
- TextEditorSpelling.cs
- XmlQueryTypeFactory.cs
- SystemKeyConverter.cs
- TypeToTreeConverter.cs
- OdbcErrorCollection.cs
- ExternalFile.cs
- SortedDictionary.cs
- XmlSchemaAppInfo.cs
- DataColumn.cs
- NumericUpDown.cs
- ActivityExecutionFilter.cs
- StretchValidation.cs
- SqlDataSource.cs
- XmlDataSourceView.cs
- LocationReferenceValue.cs
- RequestCacheValidator.cs
- HtmlInputFile.cs
- OrderedDictionary.cs
- ModelChangedEventArgsImpl.cs