ItemsPresenter.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / System / Windows / Controls / ItemsPresenter.cs / 1305600 / ItemsPresenter.cs

                            //---------------------------------------------------------------------------- 
//
// 
//    Copyright (C) Microsoft Corporation.  All rights reserved.
//  
//
// Description: ItemsPresenter object - site of the panel for layout of groups or items. 
// 
// Specs:       http://avalon/connecteddata/M5%20General%20Docs/Data%20Styling.mht
// 
//---------------------------------------------------------------------------

using System;
using System.Collections; 
using System.Diagnostics;
using System.Windows.Media; 
using MS.Internal; 
using MS.Internal.Data;                 // WeakRefKey
 
namespace System.Windows.Controls
{
    /// 
    ///     An ItemsPresenter marks the site (in a style) of the panel that controls 
    ///     layout of groups or items.
    ///  
    [Localizability(LocalizationCategory.NeverLocalize)] 
    public class ItemsPresenter : FrameworkElement
    { 
        //-----------------------------------------------------
        //
        // Public Methods
        // 
        //-----------------------------------------------------
 
        ///  
        /// Called when the Template's tree is about to be generated
        ///  
        internal override void OnPreApplyTemplate()
        {
            base.OnPreApplyTemplate();
            AttachToOwner(); 
        }
 
        ///  
        ///     This is the virtual that sub-classes must override if they wish to get
        ///     notified that the template tree has been created. 
        /// 
        public override void OnApplyTemplate()
        {
            // verify that the template produced a panel with no children 
            Panel panel = GetVisualChild(0) as Panel;
            if (panel == null || VisualTreeHelper.GetChildrenCount(panel) > 0) 
                throw new InvalidOperationException(SR.Get(SRID.ItemsPanelNotSingleNode)); 

            base.OnApplyTemplate(); 
        }

        //------------------------------------------------------
        // 
        // Protected Methods
        // 
        //----------------------------------------------------- 

        ///  
        /// Override of .
        /// 
        /// Constraint size is an "upper limit" that the return value should not exceed.
        /// The ItemsPresenter's desired size. 
        protected override Size MeasureOverride(Size constraint)
        { 
            return Helper.MeasureElementWithSingleChild(this, constraint); 
        }
 

        /// 
        /// Override of .
        ///  
        /// Size the ItemsPresenter will assume.
        protected override Size ArrangeOverride(Size arrangeSize) 
        { 
            return Helper.ArrangeElementWithSingleChild(this, arrangeSize);
        } 

        //------------------------------------------------------
        //
        // Internal Properties 
        //
        //------------------------------------------------------ 
 
        internal ItemsControl Owner
        { 
            get { return _owner; }
        }

        internal ItemContainerGenerator Generator 
        {
            get { return _generator; } 
        } 

        // 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 = (ItemsPanelTemplate)value; }
        }

        ///  
        /// TemplateProperty
        ///  
        internal static readonly DependencyProperty TemplateProperty = 
                DependencyProperty.Register(
                        "Template", 
                        typeof(ItemsPanelTemplate),
                        typeof(ItemsPresenter),
                        new FrameworkPropertyMetadata(
                                (ItemsPanelTemplate) null,  // default value 
                                FrameworkPropertyMetadataOptions.AffectsMeasure,
                                new PropertyChangedCallback(OnTemplateChanged))); 
 

        ///  
        /// Template Property
        /// 
        private ItemsPanelTemplate 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((ItemsPanelTemplate)oldTemplate, (ItemsPanelTemplate)newTemplate);
        } 

        // Property invalidation callback invoked when TemplateProperty is invalidated 
        private static void OnTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
        {
            ItemsPresenter ip = (ItemsPresenter) d; 
            StyleHelper.UpdateTemplateCache(ip, (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(ItemsPanelTemplate oldTemplate, ItemsPanelTemplate newTemplate) 
        {
        } 
 
        //-----------------------------------------------------
        // 
        // Internal Methods
        //
        //------------------------------------------------------
 
        internal static ItemsPresenter FromPanel(Panel panel)
        { 
            if (panel == null) 
                return null;
 
            return panel.TemplatedParent as ItemsPresenter;
        }

        internal static ItemsPresenter FromGroupItem(GroupItem groupItem) 
        {
            if (groupItem == null) 
                return null; 

            Visual parent = VisualTreeHelper.GetParent(groupItem) as Visual; 
            if (parent == null)
                return null;

            return VisualTreeHelper.GetParent(parent) as ItemsPresenter; 
        }
 
        internal override void OnAncestorChanged() 
        {
            if (TemplatedParent == null) 
            {
                UseGenerator(null);
                ClearPanel();
            } 

            base.OnAncestorChanged(); 
        } 

 
        //-----------------------------------------------------
        //
        // Private Methods
        // 
        //-----------------------------------------------------
 
        // initialize (called during measure, from ApplyTemplate) 
        void AttachToOwner()
        { 
            ItemsControl owner = this.TemplatedParent as ItemsControl;
            ItemContainerGenerator generator;

            if (owner != null) 
            {
                // top-level presenter - get information from ItemsControl 
                generator = owner.ItemContainerGenerator; 
            }
            else 
            {
                // subgroup presenter - get information from GroupItem
                GroupItem parentGI = this.TemplatedParent as GroupItem;
                ItemsPresenter parentIP = FromGroupItem(parentGI); 

                if (parentIP != null) 
                    owner = parentIP.Owner; 

                generator = (parentGI != null) ? parentGI.Generator : null; 
            }

            _owner = owner;
            UseGenerator(generator); 

            // create the panel, based either on ItemsControl.ItemsPanel or GroupStyle.Panel 
            GroupStyle groupStyle = (_generator != null) ? _generator.GroupStyle : null; 
            Template = (groupStyle != null) ? groupStyle.Panel
                                                : (_owner != null) ? _owner.ItemsPanel 
                                                : null;
        }

        void UseGenerator(ItemContainerGenerator generator) 
        {
            if (generator == _generator) 
                return; 

            if (_generator != null) 
                _generator.PanelChanged -= new EventHandler(OnPanelChanged);

            _generator = generator;
 
            if (_generator != null)
                _generator.PanelChanged += new EventHandler(OnPanelChanged); 
        } 

        private void OnPanelChanged(object sender, EventArgs e) 
        {
            // something has changed that affects the ItemsPresenter.
            // Re-measure.  This will recalculate everything from scratch.
            InvalidateMeasure(); 

            // 
            // If we're under a ScrollViewer then its ScrollContentPresenter needs to 
            // be updated to work with the new panel.
            // 

            ScrollViewer parent = Parent as ScrollViewer;
            if (parent != null)
            { 
                // If our logical parent is a ScrollViewer then the visual parent is a ScrollContentPresenter.
                ScrollContentPresenter scp = VisualTreeHelper.GetParent(this) as ScrollContentPresenter; 
 
                if (scp != null)
                { 
                    scp.HookupScrollingComponents();
                }
            }
        } 

        // workaround, pending bug 953483.  The panel is 
        // being removed from the tree, so it should release 
        // its resources (chiefly - stop listening for generator's
        // ItemsChanged event).  Until there's a mechanism for 
        // this, just mark the panel as a non-ItemsHost, so
        // that the next time it gets ItemsChanged it will
        // stop listening.  (See also bug 942265)
        private void ClearPanel() 
        {
            Panel oldPanel = (this.VisualChildrenCount > 0) ? this.GetVisualChild(0) as Panel : null; 
            Type type = null; 

            if( Template != null ) 
            {
                // Get the type of the template content's root

                // Is this a FEF-based template? 
                if( Template.VisualTree != null )
                { 
                    type = Template.VisualTree.Type; 
                }
 
                // Or, is it a (non-empty) Baml-based template?
                else if (Template.HasXamlNodeContent)
                {
                    System.Xaml.XamlType xType = (Template.Template as TemplateContent).RootType; 
                    type = xType.UnderlyingType;
                } 
            } 

            if (oldPanel != null && oldPanel.GetType() == type) 
            {
                oldPanel.IsItemsHost = false;
            }
        } 

        //----------------------------------------------------- 
        // 
        // Private Fields
        // 
        //------------------------------------------------------

        ItemsControl _owner;
        ItemContainerGenerator _generator; 
        ItemsPanelTemplate _templateCache;
    } 
} 

 


// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
//---------------------------------------------------------------------------- 
//
// 
//    Copyright (C) Microsoft Corporation.  All rights reserved.
//  
//
// Description: ItemsPresenter object - site of the panel for layout of groups or items. 
// 
// Specs:       http://avalon/connecteddata/M5%20General%20Docs/Data%20Styling.mht
// 
//---------------------------------------------------------------------------

using System;
using System.Collections; 
using System.Diagnostics;
using System.Windows.Media; 
using MS.Internal; 
using MS.Internal.Data;                 // WeakRefKey
 
namespace System.Windows.Controls
{
    /// 
    ///     An ItemsPresenter marks the site (in a style) of the panel that controls 
    ///     layout of groups or items.
    ///  
    [Localizability(LocalizationCategory.NeverLocalize)] 
    public class ItemsPresenter : FrameworkElement
    { 
        //-----------------------------------------------------
        //
        // Public Methods
        // 
        //-----------------------------------------------------
 
        ///  
        /// Called when the Template's tree is about to be generated
        ///  
        internal override void OnPreApplyTemplate()
        {
            base.OnPreApplyTemplate();
            AttachToOwner(); 
        }
 
        ///  
        ///     This is the virtual that sub-classes must override if they wish to get
        ///     notified that the template tree has been created. 
        /// 
        public override void OnApplyTemplate()
        {
            // verify that the template produced a panel with no children 
            Panel panel = GetVisualChild(0) as Panel;
            if (panel == null || VisualTreeHelper.GetChildrenCount(panel) > 0) 
                throw new InvalidOperationException(SR.Get(SRID.ItemsPanelNotSingleNode)); 

            base.OnApplyTemplate(); 
        }

        //------------------------------------------------------
        // 
        // Protected Methods
        // 
        //----------------------------------------------------- 

        ///  
        /// Override of .
        /// 
        /// Constraint size is an "upper limit" that the return value should not exceed.
        /// The ItemsPresenter's desired size. 
        protected override Size MeasureOverride(Size constraint)
        { 
            return Helper.MeasureElementWithSingleChild(this, constraint); 
        }
 

        /// 
        /// Override of .
        ///  
        /// Size the ItemsPresenter will assume.
        protected override Size ArrangeOverride(Size arrangeSize) 
        { 
            return Helper.ArrangeElementWithSingleChild(this, arrangeSize);
        } 

        //------------------------------------------------------
        //
        // Internal Properties 
        //
        //------------------------------------------------------ 
 
        internal ItemsControl Owner
        { 
            get { return _owner; }
        }

        internal ItemContainerGenerator Generator 
        {
            get { return _generator; } 
        } 

        // 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 = (ItemsPanelTemplate)value; }
        }

        ///  
        /// TemplateProperty
        ///  
        internal static readonly DependencyProperty TemplateProperty = 
                DependencyProperty.Register(
                        "Template", 
                        typeof(ItemsPanelTemplate),
                        typeof(ItemsPresenter),
                        new FrameworkPropertyMetadata(
                                (ItemsPanelTemplate) null,  // default value 
                                FrameworkPropertyMetadataOptions.AffectsMeasure,
                                new PropertyChangedCallback(OnTemplateChanged))); 
 

        ///  
        /// Template Property
        /// 
        private ItemsPanelTemplate 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((ItemsPanelTemplate)oldTemplate, (ItemsPanelTemplate)newTemplate);
        } 

        // Property invalidation callback invoked when TemplateProperty is invalidated 
        private static void OnTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
        {
            ItemsPresenter ip = (ItemsPresenter) d; 
            StyleHelper.UpdateTemplateCache(ip, (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(ItemsPanelTemplate oldTemplate, ItemsPanelTemplate newTemplate) 
        {
        } 
 
        //-----------------------------------------------------
        // 
        // Internal Methods
        //
        //------------------------------------------------------
 
        internal static ItemsPresenter FromPanel(Panel panel)
        { 
            if (panel == null) 
                return null;
 
            return panel.TemplatedParent as ItemsPresenter;
        }

        internal static ItemsPresenter FromGroupItem(GroupItem groupItem) 
        {
            if (groupItem == null) 
                return null; 

            Visual parent = VisualTreeHelper.GetParent(groupItem) as Visual; 
            if (parent == null)
                return null;

            return VisualTreeHelper.GetParent(parent) as ItemsPresenter; 
        }
 
        internal override void OnAncestorChanged() 
        {
            if (TemplatedParent == null) 
            {
                UseGenerator(null);
                ClearPanel();
            } 

            base.OnAncestorChanged(); 
        } 

 
        //-----------------------------------------------------
        //
        // Private Methods
        // 
        //-----------------------------------------------------
 
        // initialize (called during measure, from ApplyTemplate) 
        void AttachToOwner()
        { 
            ItemsControl owner = this.TemplatedParent as ItemsControl;
            ItemContainerGenerator generator;

            if (owner != null) 
            {
                // top-level presenter - get information from ItemsControl 
                generator = owner.ItemContainerGenerator; 
            }
            else 
            {
                // subgroup presenter - get information from GroupItem
                GroupItem parentGI = this.TemplatedParent as GroupItem;
                ItemsPresenter parentIP = FromGroupItem(parentGI); 

                if (parentIP != null) 
                    owner = parentIP.Owner; 

                generator = (parentGI != null) ? parentGI.Generator : null; 
            }

            _owner = owner;
            UseGenerator(generator); 

            // create the panel, based either on ItemsControl.ItemsPanel or GroupStyle.Panel 
            GroupStyle groupStyle = (_generator != null) ? _generator.GroupStyle : null; 
            Template = (groupStyle != null) ? groupStyle.Panel
                                                : (_owner != null) ? _owner.ItemsPanel 
                                                : null;
        }

        void UseGenerator(ItemContainerGenerator generator) 
        {
            if (generator == _generator) 
                return; 

            if (_generator != null) 
                _generator.PanelChanged -= new EventHandler(OnPanelChanged);

            _generator = generator;
 
            if (_generator != null)
                _generator.PanelChanged += new EventHandler(OnPanelChanged); 
        } 

        private void OnPanelChanged(object sender, EventArgs e) 
        {
            // something has changed that affects the ItemsPresenter.
            // Re-measure.  This will recalculate everything from scratch.
            InvalidateMeasure(); 

            // 
            // If we're under a ScrollViewer then its ScrollContentPresenter needs to 
            // be updated to work with the new panel.
            // 

            ScrollViewer parent = Parent as ScrollViewer;
            if (parent != null)
            { 
                // If our logical parent is a ScrollViewer then the visual parent is a ScrollContentPresenter.
                ScrollContentPresenter scp = VisualTreeHelper.GetParent(this) as ScrollContentPresenter; 
 
                if (scp != null)
                { 
                    scp.HookupScrollingComponents();
                }
            }
        } 

        // workaround, pending bug 953483.  The panel is 
        // being removed from the tree, so it should release 
        // its resources (chiefly - stop listening for generator's
        // ItemsChanged event).  Until there's a mechanism for 
        // this, just mark the panel as a non-ItemsHost, so
        // that the next time it gets ItemsChanged it will
        // stop listening.  (See also bug 942265)
        private void ClearPanel() 
        {
            Panel oldPanel = (this.VisualChildrenCount > 0) ? this.GetVisualChild(0) as Panel : null; 
            Type type = null; 

            if( Template != null ) 
            {
                // Get the type of the template content's root

                // Is this a FEF-based template? 
                if( Template.VisualTree != null )
                { 
                    type = Template.VisualTree.Type; 
                }
 
                // Or, is it a (non-empty) Baml-based template?
                else if (Template.HasXamlNodeContent)
                {
                    System.Xaml.XamlType xType = (Template.Template as TemplateContent).RootType; 
                    type = xType.UnderlyingType;
                } 
            } 

            if (oldPanel != null && oldPanel.GetType() == type) 
            {
                oldPanel.IsItemsHost = false;
            }
        } 

        //----------------------------------------------------- 
        // 
        // Private Fields
        // 
        //------------------------------------------------------

        ItemsControl _owner;
        ItemContainerGenerator _generator; 
        ItemsPanelTemplate _templateCache;
    } 
} 

 


// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK