DataGridColumnHeader.xaml.cs :  » 2.6.4-mono-.net-core » System.Windows » System » Windows » Controls » Primitives » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » 2.6.4 mono .net core » System.Windows 
System.Windows » System » Windows » Controls » Primitives » DataGridColumnHeader.xaml.cs
// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.

using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Windows.Automation.Peers;
using System.Windows.Input;
using System.Windows.Media;

namespace System.Windows.Controls.Primitives{
    [TemplateVisualState(Name = VisualStates.StateNormal, GroupName = VisualStates.GroupCommon)]
    [TemplateVisualState(Name = VisualStates.StateMouseOver, GroupName = VisualStates.GroupCommon)]
    [TemplateVisualState(Name = VisualStates.StateUnsorted, GroupName = VisualStates.GroupSort)]
    [TemplateVisualState(Name = VisualStates.StateSortAscending, GroupName = VisualStates.GroupSort)]
    [TemplateVisualState(Name = VisualStates.StateSortDescending, GroupName = VisualStates.GroupSort)]
    public partial class DataGridColumnHeader : ContentControl
    {
        private enum DragMode
        {
            None = 0,
            MouseDown = 1,
            Drag = 2,
            Resize = 3,
            Reorder = 4
        }

        #region Constants

        private const int DATAGRIDCOLUMNHEADER_resizeRegionWidth = 5;
        private const double DATAGRIDCOLUMNHEADER_separatorThickness = 1;

        #endregion Constants

        #region Data

        private static DragMode _dragMode;
        private static Point? _lastMousePositionGrid;
        private static double _lastResizeWidth;
        private static double _originalHorizontalOffset;
        private static double _originalWidth;
        private Visibility _desiredSeparatorVisibility;
        private static Point? _dragStart;
        private static Point? _dragStartParent;
        private static DataGridColumn _dragColumn;
        private static Popup _reorderingThumb;

        #endregion Data

        public DataGridColumnHeader()
        {
            this.LostMouseCapture += new MouseEventHandler(DataGridColumnHeader_LostMouseCapture);
            this.MouseLeftButtonDown += new MouseButtonEventHandler(DataGridColumnHeader_MouseLeftButtonDown);
            this.MouseLeftButtonUp += new MouseButtonEventHandler(DataGridColumnHeader_MouseLeftButtonUp);
            this.MouseMove += new MouseEventHandler(DataGridColumnHeader_MouseMove);
            this.MouseEnter += new MouseEventHandler(DataGridColumnHeader_MouseEnter);
            this.MouseLeave += new MouseEventHandler(DataGridColumnHeader_MouseLeave);

            DefaultStyleKey = typeof(DataGridColumnHeader);
        }

        #region Dependency Properties

        #region SeparatorBrush

        /// <summary>
        /// Gets or sets a brush used by the header separator line
        /// </summary>
        public Brush SeparatorBrush
        {
            get { return GetValue(SeparatorBrushProperty) as Brush; }
            set { SetValue(SeparatorBrushProperty, value); }
        }

        public static readonly DependencyProperty SeparatorBrushProperty = 
            DependencyProperty.Register("SeparatorBrush", 
                typeof(Brush),
                typeof(DataGridColumnHeader), 
                null);

        #endregion SeparatorBrush

        #region SeparatorVisibility

        /// <summary>
        /// Gets or sets the visibility of the header separator line
        /// </summary>
        public Visibility SeparatorVisibility
        {
            get { return (Visibility) GetValue(SeparatorVisibilityProperty); }
            set { SetValue(SeparatorVisibilityProperty, value); }
        }

        public static readonly DependencyProperty SeparatorVisibilityProperty =
            DependencyProperty.Register("SeparatorVisibility",
                typeof(Visibility),
                typeof(DataGridColumnHeader),
                new PropertyMetadata(OnSeparatorVisibilityPropertyChanged));

        private static void OnSeparatorVisibilityPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            DataGridColumnHeader columnHeader = (DataGridColumnHeader)d;
            
            if (!columnHeader.IsHandlerSuspended(e.Property))
            {
                columnHeader._desiredSeparatorVisibility = (Visibility)e.NewValue;
                if (columnHeader.OwningGrid != null)
                {
                    columnHeader.UpdateSeparatorVisibility(columnHeader.OwningGrid.ColumnsInternal.LastVisibleColumn);
                }
                else
                {
                    columnHeader.UpdateSeparatorVisibility(null);
                }
            }
        }

        #endregion SeparatorVisibility

        #endregion Dependency Properties


        #region Public Properties

        #endregion Public Properties


        #region Protected Properties

        #endregion Protected Properties

        #region Internal Properties

        internal int ColumnIndex
        {
            get
            {
                if (this.OwningColumn == null)
                {
                    return -1;
                }
                return this.OwningColumn.Index;
            }
        }

        internal ListSortDirection? CurrentSortingState
        {
            get;
            private set;
        }

        internal DataGrid OwningGrid
        {
            get
            {
                if (this.OwningColumn != null && this.OwningColumn.OwningGrid != null)
                {
                    return this.OwningColumn.OwningGrid;
                }
                return null;
            }
        }

        internal DataGridColumn OwningColumn
        {
            get;
            set;
        }

        #endregion Internal Properties


        #region Private Properties

        private bool IsMouseOver
        {
            get;
            set;
        }

        #endregion Private Properties


        #region Public Methods

        #endregion Public Methods


        #region Protected Methods

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            ApplyState();
        }

        protected override void OnContentChanged(object oldContent, object newContent)
        {
            if (newContent != null && !DataGridDataConnection.DataTypeIsPrimitive(newContent.GetType()))
            {
                throw DataGridError.DataGridColumnHeader.ContentDoesNotSupportUIElements();
            }
            base.OnContentChanged(oldContent, newContent);
        }

        /// <summary>
        /// Creates AutomationPeer (<see cref="UIElement.OnCreateAutomationPeer"/>)
        /// </summary>
        protected override AutomationPeer OnCreateAutomationPeer()
        {
            if (this.OwningGrid != null && this.OwningColumn != this.OwningGrid.ColumnsInternal.FillerColumn)
            {
                return new DataGridColumnHeaderAutomationPeer(this);
            }
            return base.OnCreateAutomationPeer();
        }

        #endregion Protected Methods


        #region Internal Methods

        internal void ApplyState()
        {
            // Common States
            if (this.IsMouseOver)
            {
                VisualStates.GoToState(this, true, VisualStates.StateMouseOver, VisualStates.StateNormal);
            }
            else
            {
                VisualStates.GoToState(this, true, VisualStates.StateNormal);
            }

            // Sort States
            this.CurrentSortingState = null;
            if (this.OwningGrid != null
                && this.OwningGrid.DataConnection != null
                && this.OwningGrid.DataConnection.AllowSort)
            {
                SortDescription? sort = this.OwningColumn.GetSortDescription();

                if (sort.HasValue)
                {
                    this.CurrentSortingState = sort.Value.Direction;
                    if (this.CurrentSortingState == ListSortDirection.Ascending)
                    {
                        VisualStates.GoToState(this, true, VisualStates.StateSortAscending, VisualStates.StateUnsorted);
                    }
                    if (this.CurrentSortingState == ListSortDirection.Descending)
                    {
                        VisualStates.GoToState(this, true, VisualStates.StateSortDescending, VisualStates.StateUnsorted);
                    }
                }
                else
                {
                    VisualStates.GoToState(this, true, VisualStates.StateUnsorted);
                }
            }
        }

        internal void InvokeProcessSort()
        {
            this.OwningGrid.CommitEdit(DataGridEditingUnit.Row, true /*exitEditingMode*/);
            this.Dispatcher.BeginInvoke(new Action(ProcessSort));
        }

        internal void OnMouseLeftButtonDown(ref bool handled, Point mousePosition)
        {
            if (handled)
            {
                return;
            }

            if (!handled && this.OwningGrid != null)
            {
                this.CaptureMouse();

                _dragMode = DragMode.MouseDown;

                _lastMousePositionGrid = this.Translate(this.OwningGrid, mousePosition);

                double distanceFromLeft = mousePosition.X;
                double distanceFromRight = this.ActualWidth - distanceFromLeft;
                DataGridColumn currentColumn = this.OwningColumn;
                DataGridColumn previousColumn = null;
                if (!(this.OwningColumn is DataGridFillerColumn))
                {
                    previousColumn = this.OwningGrid.ColumnsInternal.GetPreviousVisibleColumn(currentColumn);
                }

                if (_dragMode == DragMode.MouseDown && _dragColumn == null && (distanceFromRight <= DATAGRIDCOLUMNHEADER_resizeRegionWidth))
                {
                    handled = TrySetResizeColumn(currentColumn);
                }
                else if (_dragMode == DragMode.MouseDown && _dragColumn == null && distanceFromLeft <= DATAGRIDCOLUMNHEADER_resizeRegionWidth && previousColumn != null)
                {
                    handled = TrySetResizeColumn(previousColumn);
                }

                if (_dragMode == DragMode.Resize && _dragColumn != null)
                {
                    _dragStart = _lastMousePositionGrid;
                    _originalWidth = _dragColumn.ActualWidth;
                    _originalHorizontalOffset = this.OwningGrid.HorizontalOffset;

                    _lastResizeWidth = _originalWidth;
                    handled = true;
                }
            }
        }

        internal void OnMouseLeftButtonUp(ref bool handled, Point mousePosition)
        {
            if (handled)
            {
                return;
            }

            if (_dragMode == DragMode.MouseDown)
            {
               OnMouseLeftButtonUp_Click(ref handled);
            }
            else if (_dragMode == DragMode.Reorder)
            {
                // Find header we're hovering over
                int? targetIndex = this.GetReorderingTargetDisplayIndex(mousePosition, true /* ignoreVertical */, true /* clipToVisible */);

                if (targetIndex.HasValue)
                {
                    try
                    {
                        this.OwningColumn.DisplayIndex = targetIndex.Value;

                        DataGridColumnEventArgs ea = new DataGridColumnEventArgs(this.OwningColumn);
                        this.OwningGrid.OnColumnReordered(ea);
                    }
                    catch (InvalidOperationException e)
                    {
                        // we will no-op the frozen column situation, and just continue as if a cancel
                        if (e.Message != DataGridError.DataGrid.CannotMoveNonFrozenColumn().Message
                            && e.Message != DataGridError.DataGrid.CannotMoveFrozenColumn().Message)
                        {
                            throw;
                        }
                    }
                }

                DragCompletedEventArgs dragCompletedEventArgs = new DragCompletedEventArgs(mousePosition.X - _dragStart.Value.X, mousePosition.Y - _dragStart.Value.Y, false);
                this.OwningGrid.OnColumnHeaderDragCompleted(dragCompletedEventArgs);
            }
            else if (_dragMode == DragMode.Drag)
            {
                DragCompletedEventArgs dragCompletedEventArgs = new DragCompletedEventArgs(0, 0, false);
                this.OwningGrid.OnColumnHeaderDragCompleted(dragCompletedEventArgs);
            }

            // 
            SetDragCursor(mousePosition);

            // Variables that track drag mode states get reset in DataGridColumnHeader_LostMouseCapture
            ReleaseMouseCapture();
            handled = true;
        }

        internal void OnMouseLeftButtonUp_Click(ref bool handled)
        {
            // completed a click without dragging, so we're sorting
            InvokeProcessSort();
            handled = true;
        }

        internal void OnMouseMove(ref bool handled, Point mousePosition, Point mousePositionGridParent)
        {
            if (handled)
            {
                return;
            }

            Debug.Assert(this.OwningGrid.Parent is UIElement);

            // various useful positions
            Point mousePositionHeaders = this.Translate(this.OwningGrid.ColumnHeaders, mousePosition);
            Point mousePositionGrid = this.Translate(this.OwningGrid, mousePosition);

            double distanceFromLeft = mousePosition.X;
            double distanceFromRight = this.ActualWidth - distanceFromLeft;

            OnMouseMove_Resize(ref handled, mousePositionGrid);

            OnMouseMove_Reorder(ref handled, mousePosition, mousePositionHeaders, mousePositionGrid, mousePositionGridParent, distanceFromLeft, distanceFromRight);

            // if we still haven't done anything about moving the mouse while 
            // the button is down, we remember that we're dragging, but we don't 
            // claim to have actually handled the event
            if (_dragMode == DragMode.MouseDown)
            {
                _dragMode = DragMode.Drag;
            }

            if (_dragMode == DragMode.Drag)
            {
                DragDeltaEventArgs dragDeltaEventArgs = new DragDeltaEventArgs(mousePositionGrid.X - _lastMousePositionGrid.Value.X, mousePositionGrid.Y - _lastMousePositionGrid.Value.Y);
                this.OwningGrid.OnColumnHeaderDragDelta(dragDeltaEventArgs);
            }

            _lastMousePositionGrid = mousePositionGrid;

            SetDragCursor(mousePosition);
        }

        internal void ProcessSort()
        {
            // if we can sort:
            //  - DataConnection.AllowSort is true, and
            //  - AllowUserToSortColumns and CanSort are true, and
            //  - OwningColumn is bound, and
            //  - SortDescriptionsCollection exists, and
            //  - the column's data type is comparable
            // then try to sort
            if (this.OwningColumn != this.OwningGrid.ColumnsInternal.FillerColumn
                && this.OwningGrid.DataConnection.AllowSort
                && this.OwningGrid.CanUserSortColumns
                && this.OwningColumn.CanUserSort
                && this.OwningGrid.DataConnection.SortDescriptions != null)
            {
                ListSortDirection newSortDirection;
                SortDescription newSort;

                bool ctrl;
                bool shift;

                KeyboardHelper.GetMetaKeyState(out ctrl, out shift);

                SortDescription? sort = this.OwningColumn.GetSortDescription();

                // if shift is held down, we multi-sort, therefore if it isn't, we'll clear the sorts beforehand
                if (!shift)
                {
                    this.OwningGrid.DataConnection.SortDescriptions.Clear();
                }

                if (sort.HasValue)
                {
                    // swap direction
                    switch (sort.Value.Direction)
                    {
                        case ListSortDirection.Ascending:
                            newSortDirection = ListSortDirection.Descending;
                            break;
                        default:
                            newSortDirection = ListSortDirection.Ascending;
                            break;
                    }

                    newSort = new SortDescription(sort.Value.PropertyName, newSortDirection);

                    // changing direction should not affect sort order, so we replace this column's
                    // sort description instead of just adding it to the end of the collection
                    int oldIndex = this.OwningGrid.DataConnection.SortDescriptions.IndexOf(sort.Value);
                    if (oldIndex >= 0)
                    {
                        this.OwningGrid.DataConnection.SortDescriptions.Remove(sort.Value);
                        this.OwningGrid.DataConnection.SortDescriptions.Insert(oldIndex, newSort);
                    }
                    else
                    {
                        this.OwningGrid.DataConnection.SortDescriptions.Add(newSort);
                    }
                }
                else
                {
                    // start new sort
                    newSortDirection = ListSortDirection.Ascending;

                    string propertyName = this.OwningColumn.GetSortPropertyName();
                    // no-opt if we couldn't find a property to sort on
                    if (string.IsNullOrEmpty(propertyName))
                    {
                        return;
                    }

                    newSort = new SortDescription(propertyName, newSortDirection);

                    this.OwningGrid.DataConnection.SortDescriptions.Add(newSort);
                }

                // We've completed the sort, so send the Invoked event for the column header's automation peer
                if (AutomationPeer.ListenerExists(AutomationEvents.InvokePatternOnInvoked))
                {
                    AutomationPeer peer = FrameworkElementAutomationPeer.FromElement(this);
                    if (peer != null)
                    {
                        peer.RaiseAutomationEvent(AutomationEvents.InvokePatternOnInvoked);
                    }
                }

            }
        }

        internal void UpdateSeparatorVisibility(DataGridColumn lastVisibleColumn)
        {
            Visibility newVisibility = _desiredSeparatorVisibility;

            // Collapse separator for the last column if there is no filler column
            if (this.OwningColumn != null &&
                this.OwningGrid != null &&
                _desiredSeparatorVisibility == Visibility.Visible &&
                this.OwningColumn == lastVisibleColumn &&
                !this.OwningGrid.ColumnsInternal.FillerColumn.IsActive)
            {
                newVisibility = Visibility.Collapsed;
            }

            // Update the public property if it has changed
            if (this.SeparatorVisibility != newVisibility)
            {
                this.SetValueNoCallback(DataGridColumnHeader.SeparatorVisibilityProperty, newVisibility);
            }
        }

        #endregion Internal Methods


        #region Private Methods

        private bool CanReorderColumn(DataGridColumn column)
        {
            return this.OwningGrid.CanUserReorderColumns 
                && !(column is DataGridFillerColumn)
                && (column.CanUserReorderInternal.HasValue && column.CanUserReorderInternal.Value || !column.CanUserReorderInternal.HasValue);
        }

        private void DataGridColumnHeader_LostMouseCapture(object sender, MouseEventArgs e)
        {
            // When we stop interacting with the column headers, we need to reset the drag mode
            // and close any popups if they are open.

            _dragMode = DragMode.None;
            _dragColumn = null;
            _dragStart = null;
            _lastMousePositionGrid = null;

            if (_reorderingThumb != null)
            {
                _reorderingThumb.IsOpen = false;
            }

            if (this.OwningGrid != null)
            {
                this.OwningGrid.ColumnDropLocationIndicatorPopup.IsOpen = false;
            }
        }

        private void DataGridColumnHeader_MouseEnter(object sender, MouseEventArgs e)
        {
            if (!this.IsEnabled)
            {
                return;
            }

            this.IsMouseOver = true;
            ApplyState();
        }

        private void DataGridColumnHeader_MouseLeave(object sender, MouseEventArgs e)
        {
            if (!this.IsEnabled)
            {
                return;
            }

            this.IsMouseOver = false;
            ApplyState();
        }

        private void DataGridColumnHeader_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (this.OwningColumn == null || e.Handled || !this.IsEnabled)
            {
                return;
            }

            Point mousePosition = e.GetPosition(this);

            bool handled = e.Handled;
            
            OnMouseLeftButtonDown(ref handled, mousePosition);
            e.Handled = handled;
        }

        private void DataGridColumnHeader_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            if (this.OwningColumn == null || e.Handled || !this.IsEnabled)
            {
                return;
            } 
            
            Point mousePosition = e.GetPosition(this);

            bool handled = e.Handled;

            OnMouseLeftButtonUp(ref handled, mousePosition);
            e.Handled = handled;
        }

        private void DataGridColumnHeader_MouseMove(object sender, MouseEventArgs e)
        {
            if (this.OwningColumn == null || !this.IsEnabled)
            {
                return;
            }

            Point mousePosition = e.GetPosition(this);
            Point absolutePosition = e.GetPosition(null);

            bool handled = false;

            OnMouseMove(ref handled, mousePosition, absolutePosition);

        }

        /// <summary>
        /// Returns the column against whose top-left the reordering caret should be positioned
        /// </summary>
        /// <param name="mousePosition"></param>
        /// <param name="ignoreVertical"></param>
        /// <param name="clipToVisible"></param>
        /// <returns></returns>
        private DataGridColumn GetReorderingTargetColumn(Point mousePosition, bool ignoreVertical, bool clipToVisible)
        {
            if (!clipToVisible || (mousePosition.Within(this, this.OwningGrid, ignoreVertical) && mousePosition.Within(this, this.OwningGrid.ColumnHeaders, ignoreVertical)))
            {
                DataGridColumnHeader result = this.OwningGrid.ColumnHeaders.Children
                    .OfType<DataGridColumnHeader>()
                    .Where(header => header.OwningGrid != null && header.OwningColumn != this.OwningGrid.ColumnsInternal.FillerColumn)
                    .OrderBy(header => header.OwningColumn.DisplayIndex)
                    .FirstOrDefault(header => IsReorderTargeted(mousePosition, header, ignoreVertical));

                if (result == null)
                {
                    return this.OwningGrid.ColumnsInternal.FillerColumn;
                }
                else
                {
                    return result.OwningColumn;
                }
            }


            return null;
        }

        /// <summary>
        /// Returns the display index to set the column to
        /// </summary>
        /// <param name="mousePosition"></param>
        /// <param name="ignoreVertical"></param>
        /// <param name="clipToVisible"></param>
        /// <returns></returns>
        private int? GetReorderingTargetDisplayIndex(Point mousePosition, bool ignoreVertical, bool clipToVisible)
        {
            if (!clipToVisible || (mousePosition.Within(this, this.OwningGrid, ignoreVertical) && mousePosition.Within(this, this.OwningGrid.ColumnHeaders, ignoreVertical)))
            {
                DataGridColumnHeader result = this.OwningGrid.ColumnHeaders.Children
                    .OfType<DataGridColumnHeader>()
                    .Where(header => header.OwningGrid != null && header.OwningColumn != this.OwningGrid.ColumnsInternal.FillerColumn)
                    .OrderBy(header => header.OwningColumn.DisplayIndex)
                    .FirstOrDefault(header => IsReorderTargeted(mousePosition, header, ignoreVertical));

                if (result != null)
                {
                    if (result.OwningColumn.DisplayIndex > this.OwningColumn.DisplayIndex)
                    {
                        // later column, but we need to adjust for the index shift that would happen
                        return result.OwningColumn.DisplayIndex - 1;
                    }
                    else
                    {
                        // earlier column
                        return result.OwningColumn.DisplayIndex;
                    }
                }
                else
                {
                    // last column
                    return this.OwningGrid.Columns.Count - 1;
                }
            }

            return null;
        }

        /// <summary>
        /// Returns true if the mouse is 
        /// - to the left of the element, or within the left half of the element
        /// and
        /// - within the vertical range of the element, or ignoreVertical == true
        /// </summary>
        /// <param name="mousePosition"></param>
        /// <param name="element"></param>
        /// <param name="ignoreVertical"></param>
        /// <returns></returns>
        private bool IsReorderTargeted(Point mousePosition, FrameworkElement element, bool ignoreVertical)
        {
            Point position = this.Translate(element, mousePosition);

            return (position.X < 0 || (position.X >= 0 && position.X <= element.ActualWidth / 2))
                && (ignoreVertical || (position.Y >= 0 && position.Y <= element.ActualHeight))
                ;
        }

        private void OnMouseMove_Reorder(ref bool handled, Point mousePosition, Point mousePositionHeaders, Point mousePositionGrid, Point mousePositionGridParent, double distanceFromLeft, double distanceFromRight)
        {
            if (handled)
            {
                return;
            }

            #region handle entry into reorder mode
            if (_dragMode == DragMode.MouseDown && _dragColumn == null && (distanceFromRight > DATAGRIDCOLUMNHEADER_resizeRegionWidth && distanceFromLeft > DATAGRIDCOLUMNHEADER_resizeRegionWidth))
            {
                DragStartedEventArgs dragStartedEventArgs = new DragStartedEventArgs(mousePositionGrid.X - _lastMousePositionGrid.Value.X, mousePositionGrid.Y - _lastMousePositionGrid.Value.Y);
                this.OwningGrid.OnColumnHeaderDragStarted(dragStartedEventArgs);

                handled = CanReorderColumn(this.OwningColumn);

                if (handled)
                {
                    DataGridColumnHeader dragIndicator = new DataGridColumnHeader();
                    dragIndicator.OwningColumn = this.OwningColumn;
                    dragIndicator.IsEnabled = false;
                    dragIndicator.Content = this.Content;
                    dragIndicator.ContentTemplate = this.ContentTemplate;

                    if (this.OwningGrid.DragIndicatorStyle != null)
                    {
                        dragIndicator.Style = this.OwningGrid.DragIndicatorStyle;
                    }

                    // If the user didn't style the dragIndicator's Width, default it to the column header's width
                    if (double.IsNaN(dragIndicator.Width))
                    {
                        dragIndicator.Width = this.ActualWidth;
                    }

                    // If the user didn't style the dropLocationIndicator's Height, default to the column header's height
                    // 



                    if (double.IsNaN(this.OwningGrid.ColumnDropLocationIndicator.Height))
                    {
                        this.OwningGrid.ColumnDropLocationIndicator.Height = this.ActualHeight;
                    }

                    // pass the caret's data template to the user for modification
                    DataGridColumnReorderingEventArgs columnReorderingEventArgs = new DataGridColumnReorderingEventArgs(this.OwningColumn)
                    {
                        DropLocationIndicator = this.OwningGrid.ColumnDropLocationIndicator,
                        DragIndicator = dragIndicator
                    };
                    this.OwningGrid.OnColumnReordering(columnReorderingEventArgs);
                    if (columnReorderingEventArgs.Cancel)
                    {
                        return;
                    }

                    // The user didn't cancel, so prepare for the reorder
                    _dragColumn = this.OwningColumn;
                    _dragMode = DragMode.Reorder;
                    _dragStartParent = mousePositionGridParent;
                    // the mouse position relative to the ColumnHeader needs to be scaled to be in the same
                    // dimensions as the DataGrid, so that it doesn't get out of sync later on
                    _dragStart = this.OwningGrid.RenderTransform.Transform(mousePosition);

                    // Display the reordering thumb
                    if (_reorderingThumb == null)
                    {
                        _reorderingThumb = new Popup();
                    }

                    _reorderingThumb.Child = columnReorderingEventArgs.DragIndicator;
                    _reorderingThumb.IsOpen = true;

                    // use the data template to populate the caret
                    if (columnReorderingEventArgs.DropLocationIndicator != null)
                    {
                        Control child = columnReorderingEventArgs.DropLocationIndicator;

                        this.OwningGrid.ColumnDropLocationIndicatorPopup.Child = child;
                        this.OwningGrid.ColumnDropLocationIndicatorPopup.Height = child.ActualHeight;
                        this.OwningGrid.ColumnDropLocationIndicatorPopup.Width = child.ActualWidth;

                        this.OwningGrid.ColumnDropLocationIndicatorPopup.IsOpen = false;
                    }
                }
            }
            #endregion

            #region handle reorder mode (eg, positioning of the popup)
            if (_dragMode == DragMode.Reorder && _reorderingThumb != null)
            {
                DragDeltaEventArgs dragDeltaEventArgs = new DragDeltaEventArgs(mousePositionGrid.X - _lastMousePositionGrid.Value.X, mousePositionGrid.Y - _lastMousePositionGrid.Value.Y);
                this.OwningGrid.OnColumnHeaderDragDelta(dragDeltaEventArgs);

                _reorderingThumb.HorizontalOffset = mousePositionGridParent.X - _dragStart.Value.X;
                _reorderingThumb.VerticalOffset = _dragStartParent.Value.Y - _dragStart.Value.Y;

                // the mouse position relative to the ColumnHeadersPresenter can be scaled differently than
                // the same position relative to the DataGrid, so apply the grid's RenderTransform
                Point scaledMousePositionHeaders = this.OwningGrid.RenderTransform.Transform(mousePositionHeaders);

                // prepare some variables for clipping/hiding
                double dgX = mousePositionGridParent.X - scaledMousePositionHeaders.X;
                double dgY = mousePositionGridParent.Y - scaledMousePositionHeaders.Y;
                double dgW = this.OwningGrid.CellsWidth;
                double dgH = this.OwningGrid.CellsHeight + this.OwningGrid.ColumnHeaders.ActualHeight;

                // we need to transform the size of the clipping rectangle if the datagrid has a rendertransform set
                Point clipSize = new Point(dgW, dgH);
                clipSize = this.OwningGrid.RenderTransform.Transform(clipSize);

                // clip the thumb to the column headers region
                _reorderingThumb.Child.Clip = new RectangleGeometry
                {
                    Rect = new Rect(
                        dgX - _reorderingThumb.HorizontalOffset,
                        dgY - _reorderingThumb.VerticalOffset,
                        clipSize.X,
                        clipSize.Y
                        )
                };

                // if the datagrid has a scale transform, apply the inverse to the popup's clipping rectangle
                ScaleTransform scaleTransform = null;
                ScaleTransform gridScaleTransform = _reorderingThumb.Child.RenderTransform as ScaleTransform;
                if (gridScaleTransform != null && gridScaleTransform.ScaleY != 0.0 && gridScaleTransform.ScaleX != 0.0)
                {
                    scaleTransform = new ScaleTransform();
                    scaleTransform.ScaleX = 1.0 / gridScaleTransform.ScaleX;
                    scaleTransform.ScaleY = 1.0 / gridScaleTransform.ScaleY;
                }
                if (scaleTransform != null)
                {
                    _reorderingThumb.Child.Clip.Transform = scaleTransform;
                }

                // Find header we're hovering over
                DataGridColumn targetColumn = this.GetReorderingTargetColumn(mousePosition, true /* ignoreVertical */, true /* clipToVisible */);

                if (this.OwningGrid.ColumnDropLocationIndicator != null)
                {
                    if (targetColumn == this.OwningGrid.ColumnsInternal.FillerColumn)
                    {
                        // change target column to last column but position caret at the end

                        targetColumn = this.OwningGrid.ColumnsInternal.LastVisibleColumn;

                        Point targetPosition = this.OwningGrid.RenderTransform.Transform(this.Translate(targetColumn.HeaderCell, mousePosition));

                        this.OwningGrid.ColumnDropLocationIndicatorPopup.IsOpen = true;
                        this.OwningGrid.ColumnDropLocationIndicatorPopup.HorizontalOffset = mousePositionGridParent.X - targetPosition.X + targetColumn.HeaderCell.ActualWidth;
                        this.OwningGrid.ColumnDropLocationIndicatorPopup.VerticalOffset = mousePositionGridParent.Y - targetPosition.Y;
                    }
                    else if (targetColumn != null)
                    {
                        // try to position caret

                        Point targetPosition = this.OwningGrid.RenderTransform.Transform(this.Translate(targetColumn.HeaderCell, mousePosition));

                        this.OwningGrid.ColumnDropLocationIndicatorPopup.IsOpen = true;
                        this.OwningGrid.ColumnDropLocationIndicatorPopup.HorizontalOffset = mousePositionGridParent.X - targetPosition.X;
                        this.OwningGrid.ColumnDropLocationIndicatorPopup.VerticalOffset = mousePositionGridParent.Y - targetPosition.Y;
                    }
                    else
                    {
                        this.OwningGrid.ColumnDropLocationIndicatorPopup.IsOpen = false;
                    }

                    // hide the caret if it's off the grid -- this is not the same as clipping
                    if (this.OwningGrid.ColumnDropLocationIndicatorPopup.HorizontalOffset < dgX
                        || dgX + clipSize.X < this.OwningGrid.ColumnDropLocationIndicatorPopup.HorizontalOffset)
                    {
                        this.OwningGrid.ColumnDropLocationIndicatorPopup.IsOpen = false;
                    }
                }

                handled = true;
            }
            #endregion
        }

        private void OnMouseMove_Resize(ref bool handled, Point mousePositionGrid)
        {
            if (handled)
            {
                return;
            }

            if (_dragMode == DragMode.Resize && _dragColumn != null && _dragStart.HasValue)
            {
                // resize column

                double mouseDelta = mousePositionGrid.X - _dragStart.Value.X;
                double newWidth = _originalWidth + mouseDelta;

                if (_lastResizeWidth >= _dragColumn.MinWidth && newWidth != _lastResizeWidth)
                {
                    newWidth = Math.Max(newWidth, 0);

                    _dragColumn.Width = new DataGridLength(newWidth);
                    _lastResizeWidth = newWidth;
                    this.OwningGrid.UpdateHorizontalOffset(_originalHorizontalOffset);
                    // 
                }

                handled = true;
            }
        }

        private void SetDragCursor(Point mousePosition)
        {
            if (_dragMode != DragMode.None)
            {
                return;
            }

            // set mouse if we can resize column

            double distanceFromLeft = mousePosition.X;
            double distanceFromRight = this.ActualWidth - distanceFromLeft;
            DataGridColumn currentColumn = this.OwningColumn;
            DataGridColumn previousColumn = null;

            if (!(this.OwningColumn is DataGridFillerColumn))
            {
                previousColumn = this.OwningGrid.ColumnsInternal.GetPreviousVisibleColumn(currentColumn);
            }

            if (distanceFromRight <= DATAGRIDCOLUMNHEADER_resizeRegionWidth && currentColumn != null && currentColumn.ActualCanUserResize)
            {
                this.Cursor = Cursors.SizeWE;
            }
            else if (distanceFromLeft <= DATAGRIDCOLUMNHEADER_resizeRegionWidth && previousColumn != null && previousColumn.ActualCanUserResize)
            {
                this.Cursor = Cursors.SizeWE;
            }
            else
            {
                this.Cursor = Cursors.Arrow;
            }
        }

        private static bool TrySetResizeColumn(DataGridColumn column)
        {
            // If datagrid.CanUserResizeColumns == false, then the column can still override it
            if (column.ActualCanUserResize)
            {
                _dragColumn = column;

                _dragMode = DragMode.Resize;

                return true;
            }
            return false;
        }

        #endregion Private Methods
    }
}
www.java2v.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.