DataGridDetailsPresenter.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / System / Windows / Controls / Primitives / DataGridDetailsPresenter.cs / 1305600 / DataGridDetailsPresenter.cs

                            //---------------------------------------------------------------------------- 
//
// Copyright (C) Microsoft Corporation.  All rights reserved.
//
//--------------------------------------------------------------------------- 

using System; 
using System.Diagnostics; 
using System.Windows;
using System.Windows.Controls; 
using System.Windows.Input;
using System.Windows.Media;

namespace System.Windows.Controls.Primitives 
{
    public class DataGridDetailsPresenter : ContentPresenter 
    { 
        static DataGridDetailsPresenter()
        { 
            DefaultStyleKeyProperty.OverrideMetadata(typeof(DataGridDetailsPresenter), new FrameworkPropertyMetadata(typeof(DataGridDetailsPresenter)));
            ContentTemplateProperty.OverrideMetadata(typeof(DataGridDetailsPresenter), new FrameworkPropertyMetadata(OnNotifyPropertyChanged, OnCoerceContentTemplate));
            ContentTemplateSelectorProperty.OverrideMetadata(typeof(DataGridDetailsPresenter), new FrameworkPropertyMetadata(OnNotifyPropertyChanged, OnCoerceContentTemplateSelector));
 
            EventManager.RegisterClassHandler(typeof(DataGridDetailsPresenter), MouseLeftButtonDownEvent, new MouseButtonEventHandler(OnAnyMouseLeftButtonDownThunk), true);
        } 
 
        /// 
        ///     Instantiates a new instance of this class. 
        /// 
        public DataGridDetailsPresenter()
        {
        } 

        #region Automation 
 
        protected override System.Windows.Automation.Peers.AutomationPeer OnCreateAutomationPeer()
        { 
            return new System.Windows.Automation.Peers.DataGridDetailsPresenterAutomationPeer(this);
        }

        #endregion 

        #region Coercion 
 
        /// 
        ///     Coerces the ContentTemplate property. 
        /// 
        private static object OnCoerceContentTemplate(DependencyObject d, object baseValue)
        {
            var details = d as DataGridDetailsPresenter; 
            var row = details.DataGridRowOwner;
            var dataGrid = row != null ? row.DataGridOwner : null; 
            return DataGridHelper.GetCoercedTransferPropertyValue( 
                details,
                baseValue, 
                ContentTemplateProperty,
                row,
                DataGridRow.DetailsTemplateProperty,
                dataGrid, 
                DataGrid.RowDetailsTemplateProperty);
        } 
 
        /// 
        ///     Coerces the ContentTemplateSelector property. 
        /// 
        private static object OnCoerceContentTemplateSelector(DependencyObject d, object baseValue)
        {
            var details = d as DataGridDetailsPresenter; 
            var row = details.DataGridRowOwner;
            var dataGrid = row != null ? row.DataGridOwner : null; 
            return DataGridHelper.GetCoercedTransferPropertyValue( 
                details,
                baseValue, 
                ContentTemplateSelectorProperty,
                row,
                DataGridRow.DetailsTemplateSelectorProperty,
                dataGrid, 
                DataGrid.RowDetailsTemplateSelectorProperty);
        } 
 
        #endregion
 
        #region Row Communication

        protected internal override void OnVisualParentChanged(DependencyObject oldParent)
        { 
            base.OnVisualParentChanged(oldParent);
 
            // DataGridRow.DetailsPresenter is used by automation peers 
            // Give the Row a pointer to the RowHeader so that it can propagate down change notifications
            DataGridRow owner = DataGridRowOwner; 
            if (owner != null)
            {
                owner.DetailsPresenter = this;
 
                // At the time that a Row is prepared we can't [....] because the DetailsPresenter isn't created yet.
                // Doing it here ensures that the DetailsPresenter is in the visual tree. 
                SyncProperties(); 
            }
        } 

        private static void OnAnyMouseLeftButtonDownThunk(object sender, MouseButtonEventArgs e)
        {
            ((DataGridDetailsPresenter)sender).OnAnyMouseLeftButtonDown(e); 
        }
 
        private void OnAnyMouseLeftButtonDown(System.Windows.Input.MouseButtonEventArgs e) 
        {
            // Ignore actions if the button down arises from a different presentation source 
            if (!PresentationSource.UnderSamePresentationSource(e.OriginalSource as DependencyObject, this))
            {
                return;
            } 

            DataGridRow rowOwner = DataGridRowOwner; 
            DataGrid dataGridOwner = rowOwner != null ? rowOwner.DataGridOwner : null; 
            if ((dataGridOwner != null) && (rowOwner != null))
            { 
                // HandleSelectionForRowHeaderAndDetailsInput below sets the CurrentCell
                // of datagrid to the cell with displayindex 0 in the row.
                // This implicitly queues a request to MakeVisible command
                // of ScrollViewer. The command handler calls MakeVisible method of 
                // VirtualizingStackPanel (of rows presenter) which works only
                // when the visual's parent layout is clean. DataGridCellsPanel layout is 
                // not clean as per MakeVisible of VSP becuase we distribute the layout of cells for the 
                // sake of row headers and hence it fails. VSP.MakeVisible method requeues a request to
                // ScrollViewer.MakeVisible command hence resulting into an infinite loop. 
                // The workaround is to bring the concerned cell into the view by calling
                // ScrollIntoView so that by the time MakeVisible handler of ScrollViewer is
                // executed the cell is already visible and the handler succeeds.
                if (dataGridOwner.CurrentCell.Item != rowOwner.Item) 
                {
                    dataGridOwner.ScrollIntoView(rowOwner.Item, dataGridOwner.ColumnFromDisplayIndex(0)); 
                } 

                dataGridOwner.HandleSelectionForRowHeaderAndDetailsInput(rowOwner, /* startDragging = */ Mouse.Captured == null); 
            }
        }

        internal FrameworkElement DetailsElement 
        {
            get 
            { 
                var childrenCount = VisualTreeHelper.GetChildrenCount(this);
                if (childrenCount > 0) 
                {
                    return VisualTreeHelper.GetChild(this, 0) as FrameworkElement;
                }
 
                return null;
            } 
        } 

        ///  
        ///     Update all properties that get a value from the DataGrid
        /// 
        /// 
        ///     See comment on DataGridRow.OnDataGridChanged 
        /// 
        internal void SyncProperties() 
        { 
            DataGridRow owner = DataGridRowOwner;
            Content = owner != null ? owner.Item : null; 
            DataGridHelper.TransferProperty(this, ContentTemplateProperty);
            DataGridHelper.TransferProperty(this, ContentTemplateSelectorProperty);
        }
 
        #endregion
 
        #region Notification Propagation 

        ///  
        ///     Notifies parts that respond to changes in the properties.
        /// 
        private static void OnNotifyPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        { 
            ((DataGridDetailsPresenter)d).NotifyPropertyChanged(d, e);
        } 
 
        internal void NotifyPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        { 
            if (e.Property == DataGrid.RowDetailsTemplateProperty || e.Property == DataGridRow.DetailsTemplateProperty || e.Property == ContentTemplateProperty)
            {
                DataGridHelper.TransferProperty(this, ContentTemplateProperty);
            } 
            else if (e.Property == DataGrid.RowDetailsTemplateSelectorProperty || e.Property == DataGridRow.DetailsTemplateSelectorProperty || e.Property == ContentTemplateSelectorProperty)
            { 
                DataGridHelper.TransferProperty(this, ContentTemplateSelectorProperty); 
            }
        } 

        #endregion

        #region GridLines 

        // Different parts of the DataGrid draw different pieces of the GridLines. 
        // Rows draw a single horizontal line on the bottom.  The DataGridDetailsPresenter is the element that handles it. 

        ///  
        ///     Measure.  This is overridden so that the row can extend its size to account for a grid line on the bottom.
        /// 
        /// 
        ///  
        protected override Size MeasureOverride(Size availableSize)
        { 
            // Make space for the GridLine on the bottom. 
            // Remove space from the constraint (since it implicitly includes the GridLine's thickness),
            // call the base implementation, and add the thickness back for the returned size. 
            var row = DataGridRowOwner;
            if (row == null)
            {
                return base.MeasureOverride(availableSize); 
            }
 
            var dataGrid = row.DataGridOwner; 
            if (dataGrid == null)
            { 
                return base.MeasureOverride(availableSize);
            }

            if (row.DetailsPresenterDrawsGridLines && 
                DataGridHelper.IsGridLineVisible(dataGrid, /*isHorizontal = */ true))
            { 
                double thickness = dataGrid.HorizontalGridLineThickness; 
                Size desiredSize = base.MeasureOverride(DataGridHelper.SubtractFromSize(availableSize, thickness, /*height = */ true));
                desiredSize.Height += thickness; 
                return desiredSize;
            }
            else
            { 
                return base.MeasureOverride(availableSize);
            } 
        } 

        ///  
        ///     Arrange.  This is overriden so that the row can position its content to account for a grid line on the bottom.
        /// 
        /// Arrange size
        protected override Size ArrangeOverride(Size finalSize) 
        {
            // We don't need to adjust the Arrange position of the content.  By default it is arranged at 0,0 and we're 
            // adding a line to the bottom.  All we have to do is compress and extend the size, just like Measure. 
            var row = DataGridRowOwner;
            if (row == null) 
            {
                return base.ArrangeOverride(finalSize);
            }
 
            var dataGrid = row.DataGridOwner;
            if (dataGrid == null) 
            { 
                return base.ArrangeOverride(finalSize);
            } 

            if (row.DetailsPresenterDrawsGridLines &&
                DataGridHelper.IsGridLineVisible(dataGrid, /*isHorizontal = */ true))
            { 
                double thickness = dataGrid.HorizontalGridLineThickness;
                Size returnSize = base.ArrangeOverride(DataGridHelper.SubtractFromSize(finalSize, thickness, /*height = */ true)); 
                returnSize.Height += thickness; 
                return returnSize;
            } 
            else
            {
                return base.ArrangeOverride(finalSize);
            } 
        }
 
        ///  
        ///     OnRender.  Overriden to draw a horizontal line underneath the content.
        ///  
        /// 
        protected override void OnRender(DrawingContext drawingContext)
        {
            base.OnRender(drawingContext); 

            var row = DataGridRowOwner; 
            if (row == null) 
            {
                return; 
            }

            var dataGrid = row.DataGridOwner;
            if (dataGrid == null) 
            {
                return; 
            } 

            if (row.DetailsPresenterDrawsGridLines && 
                DataGridHelper.IsGridLineVisible(dataGrid, /*isHorizontal = */ true))
            {
                double thickness = dataGrid.HorizontalGridLineThickness;
                Rect rect = new Rect(new Size(RenderSize.Width, thickness)); 
                rect.Y = RenderSize.Height - thickness;
 
                drawingContext.DrawRectangle(dataGrid.HorizontalGridLinesBrush, null, rect); 
            }
        } 

        #endregion

        #region Helpers 

        ///  
        ///     The DataGrid that owns this control 
        /// 
        private DataGrid DataGridOwner 
        {
            get
            {
                DataGridRow owner = DataGridRowOwner; 
                if (owner != null)
                { 
                    return owner.DataGridOwner; 
                }
 
                return null;
            }
        }
 
        /// 
        ///     The DataGridRow that owns this control. 
        ///  
        internal DataGridRow DataGridRowOwner
        { 
            get { return DataGridHelper.FindParent(this); }
        }

        #endregion 
    }
} 

// 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