DataGridHelper.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 / DataGridHelper.cs / 1305600 / DataGridHelper.cs

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

using System; 
using System.Collections.Generic; 
using System.Collections.ObjectModel;
using System.ComponentModel; 
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Controls.Primitives; 
using System.Windows.Data;
using System.Windows.Input; 
using System.Windows.Media; 
using System.Windows.Threading;
using MS.Internal; 

namespace System.Windows.Controls
{
    ///  
    ///     Helper code for DataGrid.
    ///  
    internal static class DataGridHelper 
    {
        #region GridLines 

        // Common code for drawing GridLines.  Shared by DataGridDetailsPresenter, DataGridCellsPresenter, and Cell

        ///  
        ///     Returns a size based on the given one with the given double subtracted out from the Width or Height.
        ///     Used to adjust for the thickness of grid lines. 
        ///  
        public static Size SubtractFromSize(Size size, double thickness, bool height)
        { 
            if (height)
            {
                return new Size(size.Width, Math.Max(0.0, size.Height - thickness));
            } 
            else
            { 
                return new Size(Math.Max(0.0, size.Width - thickness), size.Height); 
            }
        } 

        /// 
        ///     Test if either the vertical or horizontal gridlines are visible.
        ///  
        public static bool IsGridLineVisible(DataGrid dataGrid, bool isHorizontal)
        { 
            if (dataGrid != null) 
            {
                DataGridGridLinesVisibility visibility = dataGrid.GridLinesVisibility; 

                switch (visibility)
                {
                    case DataGridGridLinesVisibility.All: 
                        return true;
                    case DataGridGridLinesVisibility.Horizontal: 
                        return isHorizontal; 
                    case DataGridGridLinesVisibility.None:
                        return false; 
                    case DataGridGridLinesVisibility.Vertical:
                        return !isHorizontal;
                }
            } 

            return false; 
        } 

        #endregion 

        #region Notification Propagation

        public static bool ShouldNotifyCells(DataGridNotificationTarget target) 
        {
            return TestTarget(target, DataGridNotificationTarget.Cells); 
        } 

        public static bool ShouldNotifyCellsPresenter(DataGridNotificationTarget target) 
        {
            return TestTarget(target, DataGridNotificationTarget.CellsPresenter);
        }
 
        public static bool ShouldNotifyColumns(DataGridNotificationTarget target)
        { 
            return TestTarget(target, DataGridNotificationTarget.Columns); 
        }
 
        public static bool ShouldNotifyColumnHeaders(DataGridNotificationTarget target)
        {
            return TestTarget(target, DataGridNotificationTarget.ColumnHeaders);
        } 

        public static bool ShouldNotifyColumnHeadersPresenter(DataGridNotificationTarget target) 
        { 
            return TestTarget(target, DataGridNotificationTarget.ColumnHeadersPresenter);
        } 

        public static bool ShouldNotifyColumnCollection(DataGridNotificationTarget target)
        {
            return TestTarget(target, DataGridNotificationTarget.ColumnCollection); 
        }
 
        public static bool ShouldNotifyDataGrid(DataGridNotificationTarget target) 
        {
            return TestTarget(target, DataGridNotificationTarget.DataGrid); 
        }

        public static bool ShouldNotifyDetailsPresenter(DataGridNotificationTarget target)
        { 
            return TestTarget(target, DataGridNotificationTarget.DetailsPresenter);
        } 
 
        public static bool ShouldRefreshCellContent(DataGridNotificationTarget target)
        { 
            return TestTarget(target, DataGridNotificationTarget.RefreshCellContent);
        }

        public static bool ShouldNotifyRowHeaders(DataGridNotificationTarget target) 
        {
            return TestTarget(target, DataGridNotificationTarget.RowHeaders); 
        } 

        public static bool ShouldNotifyRows(DataGridNotificationTarget target) 
        {
            return TestTarget(target, DataGridNotificationTarget.Rows);
        }
 
        public static bool ShouldNotifyRowSubtree(DataGridNotificationTarget target)
        { 
            DataGridNotificationTarget value = 
                DataGridNotificationTarget.Rows |
                DataGridNotificationTarget.RowHeaders | 
                DataGridNotificationTarget.CellsPresenter |
                DataGridNotificationTarget.Cells |
                DataGridNotificationTarget.RefreshCellContent |
                DataGridNotificationTarget.DetailsPresenter; 

            return TestTarget(target, value); 
        } 

        private static bool TestTarget(DataGridNotificationTarget target, DataGridNotificationTarget value) 
        {
            return (target & value) != 0;
        }
 
        #endregion
 
        #region Tree Helpers 

        ///  
        ///     Walks up the templated parent tree looking for a parent type.
        /// 
        public static T FindParent(FrameworkElement element) where T : FrameworkElement
        { 
            FrameworkElement parent = element.TemplatedParent as FrameworkElement;
 
            while (parent != null) 
            {
                T correctlyTyped = parent as T; 
                if (correctlyTyped != null)
                {
                    return correctlyTyped;
                } 

                parent = parent.TemplatedParent as FrameworkElement; 
            } 

            return null; 
        }

        public static T FindVisualParent(UIElement element) where T : UIElement
        { 
            UIElement parent = element;
            while (parent != null) 
            { 
                T correctlyTyped = parent as T;
                if (correctlyTyped != null) 
                {
                    return correctlyTyped;
                }
 
                parent = VisualTreeHelper.GetParent(parent) as UIElement;
            } 
 
            return null;
        } 

        /// 
        ///     Helper method which determines if any of the elements of
        ///     the tree is focusable and has tab stop 
        /// 
        public static bool TreeHasFocusAndTabStop(DependencyObject element) 
        { 
            if (element == null)
            { 
                return false;
            }

            UIElement uielement = element as UIElement; 
            if (uielement != null)
            { 
                if (uielement.Focusable && KeyboardNavigation.GetIsTabStop(uielement)) 
                {
                    return true; 
                }
            }
            else
            { 
                ContentElement contentElement = element as ContentElement;
                if (contentElement != null && contentElement.Focusable && KeyboardNavigation.GetIsTabStop(contentElement)) 
                { 
                    return true;
                } 
            }

            int childCount = VisualTreeHelper.GetChildrenCount(element);
            for (int i = 0; i < childCount; i++) 
            {
                DependencyObject child = VisualTreeHelper.GetChild(element, i) as DependencyObject; 
                if (TreeHasFocusAndTabStop(child)) 
                {
                    return true; 
                }
            }

            return false; 
        }
 
        #endregion 

        #region Cells Panel Helper 

        /// 
        ///     Invalidates a cell's panel if its column's width changes sufficiently.
        ///  
        /// The cell or header.
        ///  
        public static void OnColumnWidthChanged(IProvideDataGridColumn cell, DependencyPropertyChangedEventArgs e) 
        {
            Debug.Assert((cell is DataGridCell) || (cell is DataGridColumnHeader), "provideColumn should be one of the cell or header containers."); 

            UIElement element = (UIElement)cell;
            DataGridColumn column = cell.Column;
            bool isColumnHeader = (cell is DataGridColumnHeader); 

            if (column != null) 
            { 
                // determine the desired value of width for auto kind columns
                DataGridLength width = column.Width; 
                if (width.IsAuto ||
                    (!isColumnHeader && width.IsSizeToCells) ||
                    (isColumnHeader && width.IsSizeToHeader))
                { 
                    DataGridLength oldWidth = (DataGridLength)e.OldValue;
                    double desiredWidth = 0.0; 
                    if (oldWidth.UnitType != width.UnitType) 
                    {
                        double constraintWidth = column.GetConstraintWidth(isColumnHeader); 
                        if (!DoubleUtil.AreClose(element.DesiredSize.Width, constraintWidth))
                        {
                            element.InvalidateMeasure();
                            element.Measure(new Size(constraintWidth, double.PositiveInfinity)); 
                        }
 
                        desiredWidth = element.DesiredSize.Width; 
                    }
                    else 
                    {
                        desiredWidth = oldWidth.DesiredValue;
                    }
 
                    if (DoubleUtil.IsNaN(width.DesiredValue) ||
                        DoubleUtil.LessThan(width.DesiredValue, desiredWidth)) 
                    { 
                        column.SetWidthInternal(new DataGridLength(width.Value, width.UnitType, desiredWidth, width.DisplayValue));
                    } 
                }
            }
        }
 
        /// 
        ///     Helper method which returns the clip for the cell based on whether it overlaps with frozen columns or not 
        ///  
        /// The cell or header.
        ///  
        public static Geometry GetFrozenClipForCell(IProvideDataGridColumn cell)
        {
            DataGridCellsPanel panel = GetParentPanelForCell(cell);
            if (panel != null) 
            {
                return panel.GetFrozenClipForChild((UIElement)cell); 
            } 

            return null; 
        }

        /// 
        ///     Helper method which returns the parent DataGridCellsPanel for a cell 
        /// 
        /// The cell or header. 
        /// Parent panel of the given cell or header 
        public static DataGridCellsPanel GetParentPanelForCell(IProvideDataGridColumn cell)
        { 
            Debug.Assert((cell is DataGridCell) || (cell is DataGridColumnHeader), "provideColumn should be one of the cell or header containers.");

            UIElement element = (UIElement)cell;
            return VisualTreeHelper.GetParent(element) as DataGridCellsPanel; 
        }
 
        ///  
        ///     Helper method which returns the parent DataGridCellPanel's offset from the scroll viewer
        ///     for a cell or Header 
        /// 
        /// The cell or header.
        /// Parent Panel's offset with respect to scroll viewer
        public static double GetParentCellsPanelHorizontalOffset(IProvideDataGridColumn cell) 
        {
            DataGridCellsPanel panel = GetParentPanelForCell(cell); 
            if (panel != null) 
            {
                return panel.ComputeCellsPanelHorizontalOffset(); 
            }

            return 0.0;
        } 

        #endregion 
 
        #region Property Helpers
 
        public static bool IsDefaultValue(DependencyObject d, DependencyProperty dp)
        {
            return DependencyPropertyHelper.GetValueSource(d, dp).BaseValueSource == BaseValueSource.Default;
        } 

        public static object GetCoercedTransferPropertyValue( 
            DependencyObject baseObject, 
            object baseValue,
            DependencyProperty baseProperty, 
            DependencyObject parentObject,
            DependencyProperty parentProperty)
        {
            return GetCoercedTransferPropertyValue( 
                baseObject,
                baseValue, 
                baseProperty, 
                parentObject,
                parentProperty, 
                null,
                null);
        }
 
        /// 
        ///     Computes the value of a given property based on the DataGrid property transfer rules. 
        ///  
        /// 
        ///     This is intended to be called from within the coercion of the baseProperty. 
        /// 
        /// The target object which recieves the transferred property
        /// The baseValue that was passed into the coercion delegate
        /// The property that is being coerced 
        /// The object that contains the parentProperty
        /// A property who's value should be transfered (via coercion) to the baseObject if it has a higher precedence. 
        /// Same as parentObject but evaluated at a lower presedece for a given BaseValueSource 
        /// Same as parentProperty but evaluated at a lower presedece for a given BaseValueSource
        ///  
        public static object GetCoercedTransferPropertyValue(
            DependencyObject baseObject,
            object baseValue,
            DependencyProperty baseProperty, 
            DependencyObject parentObject,
            DependencyProperty parentProperty, 
            DependencyObject grandParentObject, 
            DependencyProperty grandParentProperty)
        { 
            // Transfer Property Coercion rules:
            //
            // Determine if this is a 'Transfer Property Coercion'.  If so:
            //   We can safely get the BaseValueSource because the property change originated from another 
            //   property, and thus this BaseValueSource wont be stale.
            //   Pick a value to use based on who has the greatest BaseValueSource 
            // If not a 'Transfer Property Coercion', simply return baseValue.  This will cause a property change if the value changes, which 
            // will trigger a 'Transfer Property Coercion', and we will no longer have a stale BaseValueSource
            var coercedValue = baseValue; 

            if (IsPropertyTransferEnabled(baseObject, baseProperty))
            {
                var propertySource = DependencyPropertyHelper.GetValueSource(baseObject, baseProperty); 
                var maxBaseValueSource = propertySource.BaseValueSource;
 
                if (parentObject != null) 
                {
                    var parentPropertySource = DependencyPropertyHelper.GetValueSource(parentObject, parentProperty); 

                    if (parentPropertySource.BaseValueSource > maxBaseValueSource)
                    {
                        coercedValue = parentObject.GetValue(parentProperty); 
                        maxBaseValueSource = parentPropertySource.BaseValueSource;
                    } 
                } 

                if (grandParentObject != null) 
                {
                    var grandParentPropertySource = DependencyPropertyHelper.GetValueSource(grandParentObject, grandParentProperty);

                    if (grandParentPropertySource.BaseValueSource > maxBaseValueSource) 
                    {
                        coercedValue = grandParentObject.GetValue(grandParentProperty); 
                        maxBaseValueSource = grandParentPropertySource.BaseValueSource; 
                    }
                } 
            }

            return coercedValue;
        } 

        ///  
        ///     Causes the given DependencyProperty to be coerced in transfer mode. 
        /// 
        ///  
        ///     This should be called from within the target object's NotifyPropertyChanged.  It MUST be called in
        ///     response to a change in the target property.
        /// 
        /// The DependencyObject which contains the property that needs to be transfered. 
        /// The DependencyProperty that is the target of the property transfer.
        public static void TransferProperty(DependencyObject d, DependencyProperty p) 
        { 
            var transferEnabledMap = GetPropertyTransferEnabledMapForObject(d);
            transferEnabledMap[p] = true; 
            d.CoerceValue(p);
            transferEnabledMap[p] = false;
        }
 
        private static Dictionary GetPropertyTransferEnabledMapForObject(DependencyObject d)
        { 
            Dictionary propertyTransferEnabledForObject; 

            if (!_propertyTransferEnabledMap.TryGetValue(d, out propertyTransferEnabledForObject)) 
            {
                propertyTransferEnabledForObject = new Dictionary();
                _propertyTransferEnabledMap.Add(d, propertyTransferEnabledForObject);
            } 

            return propertyTransferEnabledForObject; 
        } 

        internal static bool IsPropertyTransferEnabled(DependencyObject d, DependencyProperty p) 
        {
            Dictionary propertyTransferEnabledForObject;

            if ( _propertyTransferEnabledMap.TryGetValue(d, out propertyTransferEnabledForObject)) 
            {
                bool isPropertyTransferEnabled; 
                if (propertyTransferEnabledForObject.TryGetValue(p, out isPropertyTransferEnabled)) 
                {
                    return isPropertyTransferEnabled; 
                }
            }

            return false; 
        }
 
        ///  
        ///     Tracks which properties are currently being transfered.  This information is needed when GetPropertyTransferEnabledMapForObject
        ///     is called inside of Coercion. 
        /// 
        private static ConditionalWeakTable> _propertyTransferEnabledMap = new ConditionalWeakTable>();

        #endregion 

        #region Binding 
 
        /// 
        ///     Returns true if the binding (or any part of it) is OneWay. 
        /// 
        internal static bool IsOneWay(BindingBase bindingBase)
        {
            if (bindingBase == null) 
            {
                return false; 
            } 

            // If it is a standard Binding, then check if it's Mode is OneWay 
            Binding binding = bindingBase as Binding;
            if (binding != null)
            {
                return binding.Mode == BindingMode.OneWay; 
            }
 
            // A multi-binding can be OneWay as well 
            MultiBinding multiBinding = bindingBase as MultiBinding;
            if (multiBinding != null) 
            {
                return multiBinding.Mode == BindingMode.OneWay;
            }
 
            // A priority binding is a list of bindings, if any are OneWay, we'll call it OneWay
            PriorityBinding priBinding = bindingBase as PriorityBinding; 
            if (priBinding != null) 
            {
                Collection subBindings = priBinding.Bindings; 
                int count = subBindings.Count;
                for (int i = 0; i < count; i++)
                {
                    if (IsOneWay(subBindings[i])) 
                    {
                        return true; 
                    } 
                }
            } 

            return false;
        }
 
        internal static BindingExpression GetBindingExpression(FrameworkElement element, DependencyProperty dp)
        { 
            if (element != null) 
            {
                return element.GetBindingExpression(dp); 
            }

            return null;
        } 

        internal static bool ValidateWithoutUpdate(FrameworkElement element) 
        { 
            bool result = true;
            BindingGroup bindingGroup = element.BindingGroup; 
            DataGridCell cell = (element != null) ? element.Parent as DataGridCell : null;

            if (bindingGroup != null && cell != null)
            { 
                Collection expressions = bindingGroup.BindingExpressions;
                for (int i=expressions.Count-1; i>=0; --i) 
                { 
                    BindingExpressionBase beb = expressions[i];
                    if (VisualTreeHelper.IsAncestorOf(cell, beb.TargetElement, typeof(DataGridCell))) 
                    {
                        result = beb.ValidateWithoutUpdate() && result;
                    }
                } 
            }
 
            return result; 
        }
 
        internal static void UpdateTarget(FrameworkElement element)
        {
            BindingGroup bindingGroup = element.BindingGroup;
            DataGridCell cell = (element != null) ? element.Parent as DataGridCell : null; 

            if (bindingGroup != null && cell != null) 
            { 
                Collection expressions = bindingGroup.BindingExpressions;
                for (int i=expressions.Count-1; i>=0; --i) 
                {
                    BindingExpressionBase beb = expressions[i];
                    if (VisualTreeHelper.IsAncestorOf(cell, beb.TargetElement, typeof(DataGridCell)))
                    { 
                        beb.UpdateTarget();
                    } 
                } 
            }
        } 

        internal static void SyncColumnProperty(DependencyObject column, DependencyObject content, DependencyProperty contentProperty, DependencyProperty columnProperty)
        {
            if (IsDefaultValue(column, columnProperty)) 
            {
                content.ClearValue(contentProperty); 
            } 
            else
            { 
                content.SetValue(contentProperty, column.GetValue(columnProperty));
            }
        }
 
        internal static string GetPathFromBinding(Binding binding)
        { 
            if (binding != null) 
            {
                if (!string.IsNullOrEmpty(binding.XPath)) 
                {
                    return binding.XPath;
                }
                else if (binding.Path != null) 
                {
                    return binding.Path.Path; 
                } 
            }
 
            return null;
        }

        #endregion 

        #region Other Helpers 
 
        /// 
        ///     Method which takes in DataGridHeadersVisibility parameter 
        ///     and determines if row headers are visible.
        /// 
        public static bool AreRowHeadersVisible(DataGridHeadersVisibility headersVisibility)
        { 
            return (headersVisibility & DataGridHeadersVisibility.Row) == DataGridHeadersVisibility.Row;
        } 
 
        /// 
        ///     Helper method which coerces a value such that it satisfies min and max restrictions 
        /// 
        public static double CoerceToMinMax(double value, double minValue, double maxValue)
        {
            value = Math.Max(value, minValue); 
            value = Math.Min(value, maxValue);
            return value; 
        } 

        ///  
        ///     Helper to check if TextCompositionEventArgs.Text has any non
        ///     escape characters.
        /// 
        public static bool HasNonEscapeCharacters(TextCompositionEventArgs textArgs) 
        {
            if (textArgs != null) 
            { 
                string text = textArgs.Text;
                for (int i = 0, count = text.Length; i < count; i++) 
                {
                    if (text[i] != _escapeChar)
                    {
                        return true; 
                    }
                } 
            } 

            return false; 
        }

        private const char _escapeChar = '\u001b';
 
        #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