//--------------------------------------------------------------------------- // // Copyright (C) Microsoft Corporation. All rights reserved. // //--------------------------------------------------------------------------- using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Windows; using System.Windows.Automation.Peers; using System.Windows.Controls; using System.Windows.Controls.Primitives; using System.Windows.Input; using System.Windows.Media; using EGC = ExtendedGrid.Microsoft.Windows.Controls; using MS.Internal; namespace ExtendedGrid.Microsoft.Windows.Controls { /// /// Container for the Column header object. This is instantiated by the DataGridColumnHeadersPresenter. /// [TemplatePart(Name = "PART_LeftHeaderGripper", Type = typeof(Thumb))] [TemplatePart(Name = "PART_RightHeaderGripper", Type = typeof(Thumb))] public class DataGridColumnHeader : ButtonBase, EGC.IProvideDataGridColumn { #region Constructors static DataGridColumnHeader() { DefaultStyleKeyProperty.OverrideMetadata(typeof(EGC.DataGridColumnHeader), new FrameworkPropertyMetadata(typeof(EGC.DataGridColumnHeader))); ContentProperty.OverrideMetadata(typeof(EGC.DataGridColumnHeader), new FrameworkPropertyMetadata(OnNotifyPropertyChanged, OnCoerceContent)); ContentTemplateProperty.OverrideMetadata(typeof(EGC.DataGridColumnHeader), new FrameworkPropertyMetadata(null, OnNotifyPropertyChanged, OnCoerceContentTemplate)); ContentTemplateSelectorProperty.OverrideMetadata(typeof(EGC.DataGridColumnHeader), new FrameworkPropertyMetadata(null, OnNotifyPropertyChanged, OnCoerceContentTemplateSelector)); ContentStringFormatProperty.OverrideMetadata(typeof(EGC.DataGridColumnHeader), new FrameworkPropertyMetadata(null, OnNotifyPropertyChanged, OnCoerceStringFormat)); StyleProperty.OverrideMetadata(typeof(EGC.DataGridColumnHeader), new FrameworkPropertyMetadata(null, OnNotifyPropertyChanged, OnCoerceStyle)); HeightProperty.OverrideMetadata(typeof(EGC.DataGridColumnHeader), new FrameworkPropertyMetadata(OnNotifyPropertyChanged, OnCoerceHeight)); FocusableProperty.OverrideMetadata(typeof(EGC.DataGridColumnHeader), new FrameworkPropertyMetadata(false)); ClipProperty.OverrideMetadata(typeof(EGC.DataGridColumnHeader), new FrameworkPropertyMetadata(null, OnCoerceClip)); } /// /// Instantiates a new instance of this class. /// public DataGridColumnHeader() { _tracker = new EGC.ContainerTracking(this); } #endregion #region Public API /// /// The Column associated with this DataGridColumnHeader. /// public EGC.DataGridColumn Column { get { return _column; } } /// /// Property that indicates the brush to use when drawing seperators between headers. /// public Brush SeparatorBrush { get { return (Brush)GetValue(SeparatorBrushProperty); } set { SetValue(SeparatorBrushProperty, value); } } /// /// DependencyProperty for SeperatorBrush. /// public static readonly DependencyProperty SeparatorBrushProperty = DependencyProperty.Register("SeparatorBrush", typeof(Brush), typeof(EGC.DataGridColumnHeader), new FrameworkPropertyMetadata(null)); /// /// Property that indicates the Visibility for the header seperators. /// public Visibility SeparatorVisibility { get { return (Visibility)GetValue(SeparatorVisibilityProperty); } set { SetValue(SeparatorVisibilityProperty, value); } } /// /// DependencyProperty for SeperatorBrush. /// public static readonly DependencyProperty SeparatorVisibilityProperty = DependencyProperty.Register("SeparatorVisibility", typeof(Visibility), typeof(EGC.DataGridColumnHeader), new FrameworkPropertyMetadata(Visibility.Visible)); #endregion #region Column Header Generation /// /// Prepares a column header to be used. Sets up the association between the column header and its column. /// internal void PrepareColumnHeader(object item, EGC.DataGridColumn column) { Debug.Assert(column != null, "This header must have been generated with for a particular column"); Debug.Assert(column.Header == item, "The data item for a ColumnHeader is the Header property of a column"); _column = column; TabIndex = column.DisplayIndex; EGC.DataGridHelper.TransferProperty(this, ContentProperty); EGC.DataGridHelper.TransferProperty(this, ContentTemplateProperty); EGC.DataGridHelper.TransferProperty(this, ContentTemplateSelectorProperty); EGC.DataGridHelper.TransferProperty(this, ContentStringFormatProperty); EGC.DataGridHelper.TransferProperty(this, StyleProperty); EGC.DataGridHelper.TransferProperty(this, HeightProperty); CoerceValue(CanUserSortProperty); CoerceValue(SortDirectionProperty); CoerceValue(IsFrozenProperty); CoerceValue(ClipProperty); CoerceValue(DisplayIndexProperty); } internal void ClearHeader() { _column = null; } /// /// Used by the DataGridRowGenerator owner to send notifications to the cell container. /// internal EGC.ContainerTracking Tracker { get { return _tracker; } } #endregion #region Resize Gripper /// /// DependencyPropertyKey for DisplayIndex property /// private static readonly DependencyPropertyKey DisplayIndexPropertyKey = DependencyProperty.RegisterReadOnly( "DisplayIndex", typeof(int), typeof(EGC.DataGridColumnHeader), new FrameworkPropertyMetadata(-1, new PropertyChangedCallback(OnDisplayIndexChanged), new CoerceValueCallback(OnCoerceDisplayIndex))); /// /// The DependencyProperty for the DisplayIndex property. /// public static readonly DependencyProperty DisplayIndexProperty = DisplayIndexPropertyKey.DependencyProperty; /// /// The property which represents the displayindex of the column corresponding to this header /// public int DisplayIndex { get { return (int)GetValue(DisplayIndexProperty); } } /// /// Coercion callback for DisplayIndex property /// private static object OnCoerceDisplayIndex(DependencyObject d, object baseValue) { EGC.DataGridColumnHeader header = (EGC.DataGridColumnHeader)d; EGC.DataGridColumn column = header.Column; if (column != null) { return column.DisplayIndex; } return -1; } /// /// Property changed call back for DisplayIndex property. /// Sets the visibility of resize grippers accordingly /// /// /// private static void OnDisplayIndexChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { EGC.DataGridColumnHeader header = (EGC.DataGridColumnHeader)d; EGC.DataGridColumn column = header.Column; if (column != null) { EGC.DataGrid dataGrid = column.DataGridOwner; if (dataGrid != null) { header.SetLeftGripperVisibility(); EGC.DataGridColumnHeader nextColumnHeader = dataGrid.ColumnHeaderFromDisplayIndex(header.DisplayIndex + 1); if (nextColumnHeader != null) { nextColumnHeader.SetLeftGripperVisibility(column.CanUserResize); } } } } /// /// Override for FrameworkElement.OnApplyTemplate /// public override void OnApplyTemplate() { base.OnApplyTemplate(); HookupGripperEvents(); } /// /// Find grippers and register drag events /// /// The default style for DataGridHeader is /// +-------------------------------+ /// +---------+ +---------+ /// + Gripper + Header + Gripper + /// + + + + /// +---------+ +---------+ /// +-------------------------------+ /// /// The reason we have two grippers is we can't extend the right gripper to straddle the line between two /// headers; the header to the right would render on top of it. /// We resize a column by grabbing the gripper to the right; the leftmost gripper thus adjusts the width of /// the column to its left. /// private void HookupGripperEvents() { UnhookGripperEvents(); _leftGripper = GetTemplateChild(LeftHeaderGripperTemplateName) as Thumb; _rightGripper = GetTemplateChild(RightHeaderGripperTemplateName) as Thumb; if (_leftGripper != null) { _leftGripper.DragStarted += new DragStartedEventHandler(OnColumnHeaderGripperDragStarted); _leftGripper.DragDelta += new DragDeltaEventHandler(OnColumnHeaderResize); _leftGripper.DragCompleted += new DragCompletedEventHandler(OnColumnHeaderGripperDragCompleted); _leftGripper.MouseDoubleClick += new MouseButtonEventHandler(OnGripperDoubleClicked); SetLeftGripperVisibility(); } if (_rightGripper != null) { _rightGripper.DragStarted += new DragStartedEventHandler(OnColumnHeaderGripperDragStarted); _rightGripper.DragDelta += new DragDeltaEventHandler(OnColumnHeaderResize); _rightGripper.DragCompleted += new DragCompletedEventHandler(OnColumnHeaderGripperDragCompleted); _rightGripper.MouseDoubleClick += new MouseButtonEventHandler(OnGripperDoubleClicked); SetRightGripperVisibility(); } } /// /// Clear gripper event /// private void UnhookGripperEvents() { if (_leftGripper != null) { _leftGripper.DragStarted -= new DragStartedEventHandler(OnColumnHeaderGripperDragStarted); _leftGripper.DragDelta -= new DragDeltaEventHandler(OnColumnHeaderResize); _leftGripper.DragCompleted -= new DragCompletedEventHandler(OnColumnHeaderGripperDragCompleted); _leftGripper.MouseDoubleClick -= new MouseButtonEventHandler(OnGripperDoubleClicked); _leftGripper = null; } if (_rightGripper != null) { _rightGripper.DragStarted -= new DragStartedEventHandler(OnColumnHeaderGripperDragStarted); _rightGripper.DragDelta -= new DragDeltaEventHandler(OnColumnHeaderResize); _rightGripper.DragCompleted -= new DragCompletedEventHandler(OnColumnHeaderGripperDragCompleted); _rightGripper.MouseDoubleClick -= new MouseButtonEventHandler(OnGripperDoubleClicked); _rightGripper = null; } } /// /// Returns either this header or the one before it depending on which Gripper fired the event. /// /// private EGC.DataGridColumnHeader HeaderToResize(object gripper) { return (gripper == _rightGripper) ? this : PreviousHeader; } // Save the original widths before header resize private void OnColumnHeaderGripperDragStarted(object sender, DragStartedEventArgs e) { EGC.DataGridColumnHeader header = HeaderToResize(sender); if (header != null) { if (header.Column != null) { EGC.DataGrid dataGrid = header.Column.DataGridOwner; if (dataGrid != null) { dataGrid.InternalColumns.OnColumnResizeStarted(); } } e.Handled = true; } } private void OnColumnHeaderResize(object sender, DragDeltaEventArgs e) { EGC.DataGridColumnHeader header = HeaderToResize(sender); if (header != null) { RecomputeColumnWidthsOnColumnResize(header, e.HorizontalChange); e.Handled = true; } } /// /// Method which recomputes the widths of columns on resize of a header /// private static void RecomputeColumnWidthsOnColumnResize(EGC.DataGridColumnHeader header, double horizontalChange) { Debug.Assert(header != null, "Header should not be null"); EGC.DataGridColumn resizingColumn = header.Column; if (resizingColumn == null) { return; } EGC.DataGrid dataGrid = resizingColumn.DataGridOwner; if (dataGrid == null) { return; } dataGrid.InternalColumns.RecomputeColumnWidthsOnColumnResize(resizingColumn, horizontalChange, false); } private void OnColumnHeaderGripperDragCompleted(object sender, DragCompletedEventArgs e) { EGC.DataGridColumnHeader header = HeaderToResize(sender); if (header != null) { if (header.Column != null) { EGC.DataGrid dataGrid = header.Column.DataGridOwner; if (dataGrid != null) { dataGrid.InternalColumns.OnColumnResizeCompleted(e.Canceled); } } e.Handled = true; } } private void OnGripperDoubleClicked(object sender, MouseButtonEventArgs e) { EGC.DataGridColumnHeader header = HeaderToResize(sender); if (header != null && header.Column != null) { header.Column.Width = EGC.DataGridLength.Auto; e.Handled = true; } } private EGC.DataGridLength ColumnWidth { get { return Column != null ? Column.Width : EGC.DataGridLength.Auto; } } private double ColumnActualWidth { get { return Column != null ? Column.ActualWidth : ActualWidth; } } #endregion #region Property Change Notification Propagation /// /// Notifies the Header of a property change. /// private static void OnNotifyPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ((EGC.DataGridColumnHeader)d).NotifyPropertyChanged(d, e); } /// /// Notification for column header-related DependencyProperty changes from the grid or from columns. /// internal void NotifyPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { EGC.DataGridColumn column = d as EGC.DataGridColumn; if ((column != null) && (column != Column)) { // This notification does not apply to this column header return; } if (e.Property == EGC.DataGridColumn.WidthProperty) { EGC.DataGridHelper.OnColumnWidthChanged(this, e); } else if (e.Property == EGC.DataGridColumn.HeaderProperty || e.Property == ContentProperty) { EGC.DataGridHelper.TransferProperty(this, ContentProperty); } else if (e.Property == EGC.DataGridColumn.HeaderTemplateProperty || e.Property == ContentTemplateProperty) { EGC.DataGridHelper.TransferProperty(this, ContentTemplateProperty); } else if (e.Property == EGC.DataGridColumn.HeaderTemplateSelectorProperty || e.Property == ContentTemplateSelectorProperty) { EGC.DataGridHelper.TransferProperty(this, ContentTemplateSelectorProperty); } else if (e.Property == EGC.DataGridColumn.HeaderStringFormatProperty || e.Property == ContentStringFormatProperty) { EGC.DataGridHelper.TransferProperty(this, ContentStringFormatProperty); } else if (e.Property == EGC.DataGrid.ColumnHeaderStyleProperty || e.Property == EGC.DataGridColumn.HeaderStyleProperty || e.Property == StyleProperty) { EGC.DataGridHelper.TransferProperty(this, StyleProperty); } else if (e.Property == EGC.DataGrid.ColumnHeaderHeightProperty || e.Property == HeightProperty) { EGC.DataGridHelper.TransferProperty(this, HeightProperty); } else if (e.Property == EGC.DataGridColumn.DisplayIndexProperty) { CoerceValue(DisplayIndexProperty); TabIndex = column.DisplayIndex; } else if (e.Property == EGC.DataGrid.CanUserResizeColumnsProperty) { OnCanUserResizeColumnsChanged(); } else if (e.Property == EGC.DataGridColumn.CanUserSortProperty) { CoerceValue(CanUserSortProperty); } else if (e.Property == EGC.DataGridColumn.SortDirectionProperty) { CoerceValue(SortDirectionProperty); } else if (e.Property == EGC.DataGridColumn.IsFrozenProperty) { CoerceValue(IsFrozenProperty); } else if (e.Property == EGC.DataGridColumn.CanUserResizeProperty) { OnCanUserResizeChanged(); } } private void OnCanUserResizeColumnsChanged() { Debug.Assert(Column != null, "column can't be null if we got a notification for this property change"); if (Column.DataGridOwner != null) { SetLeftGripperVisibility(); SetRightGripperVisibility(); } } private void OnCanUserResizeChanged() { Debug.Assert(Column != null, "column can't be null if we got a notification for this property change"); EGC.DataGrid dataGrid = Column.DataGridOwner; if (dataGrid != null) { EGC.DataGridColumnHeader nextColumnHeader = dataGrid.ColumnHeaderFromDisplayIndex(DisplayIndex + 1); if (nextColumnHeader != null) { nextColumnHeader.SetLeftGripperVisibility(Column.CanUserResize); } SetRightGripperVisibility(); } } private void SetLeftGripperVisibility() { if (_leftGripper == null || Column == null) { return; } int displayIndex = DisplayIndex; bool canPrevColumnResize = (displayIndex > 0 ? Column.DataGridOwner.ColumnFromDisplayIndex(displayIndex - 1).CanUserResize : false); SetLeftGripperVisibility(canPrevColumnResize); } private void SetLeftGripperVisibility(bool canPreviousColumnResize) { if (_leftGripper == null || Column == null) { return; } EGC.DataGrid dataGrid = Column.DataGridOwner; if (dataGrid != null && dataGrid.CanUserResizeColumns && canPreviousColumnResize) { _leftGripper.Visibility = Visibility.Visible; } else { _leftGripper.Visibility = Visibility.Collapsed; } } private void SetRightGripperVisibility() { if (_rightGripper == null || Column == null) { return; } EGC.DataGrid dataGrid = Column.DataGridOwner; if (dataGrid != null && dataGrid.CanUserResizeColumns && Column.CanUserResize) { _rightGripper.Visibility = Visibility.Visible; } else { _rightGripper.Visibility = Visibility.Collapsed; } } #endregion #region Style and Template Coercion callbacks /// /// Coerces the Content property. We're choosing a value between Column.Header and the Content property on ColumnHeader. /// private static object OnCoerceContent(DependencyObject d, object baseValue) { var header = d as EGC.DataGridColumnHeader; return EGC.DataGridHelper.GetCoercedTransferPropertyValue( header, baseValue, ContentProperty, header.Column, EGC.DataGridColumn.HeaderProperty); } /// /// Coerces the ContentTemplate property based on the templates defined on the Column. /// private static object OnCoerceContentTemplate(DependencyObject d, object baseValue) { var columnHeader = d as EGC.DataGridColumnHeader; return EGC.DataGridHelper.GetCoercedTransferPropertyValue( columnHeader, baseValue, ContentTemplateProperty, columnHeader.Column, EGC.DataGridColumn.HeaderTemplateProperty); } /// /// Coerces the ContentTemplateSelector property based on the selector defined on the Column. /// private static object OnCoerceContentTemplateSelector(DependencyObject d, object baseValue) { var columnHeader = d as EGC.DataGridColumnHeader; return EGC.DataGridHelper.GetCoercedTransferPropertyValue( columnHeader, baseValue, ContentTemplateSelectorProperty, columnHeader.Column, EGC.DataGridColumn.HeaderTemplateSelectorProperty); } /// /// Coerces the ContentStringFormat property based on the templates defined on the Column. /// private static object OnCoerceStringFormat(DependencyObject d, object baseValue) { var columnHeader = d as EGC.DataGridColumnHeader; return EGC.DataGridHelper.GetCoercedTransferPropertyValue( columnHeader, baseValue, ContentStringFormatProperty, columnHeader.Column, EGC.DataGridColumn.HeaderStringFormatProperty); } /// /// Coerces the Style property based on the templates defined on the Column or DataGrid. /// private static object OnCoerceStyle(DependencyObject d, object baseValue) { var columnHeader = d as EGC.DataGridColumnHeader; var column = columnHeader.Column; var dataGrid = column != null ? column.DataGridOwner : null; return EGC.DataGridHelper.GetCoercedTransferPropertyValue( columnHeader, baseValue, StyleProperty, column, EGC.DataGridColumn.HeaderStyleProperty, dataGrid, EGC.DataGrid.ColumnHeaderStyleProperty); } #endregion #region Auto Sort /// /// DependencyPropertyKey for CanUserSort property /// private static readonly DependencyPropertyKey CanUserSortPropertyKey = DependencyProperty.RegisterReadOnly( "CanUserSort", typeof(bool), typeof(EGC.DataGridColumnHeader), new FrameworkPropertyMetadata(true, null, new CoerceValueCallback(OnCoerceCanUserSort))); /// /// The DependencyProperty for the CanUserSort property. /// public static readonly DependencyProperty CanUserSortProperty = CanUserSortPropertyKey.DependencyProperty; /// /// CanUserSort is the flag which determines if the datagrid can be sorted based on the column of this header /// public bool CanUserSort { get { return (bool)GetValue(CanUserSortProperty); } } /// /// DependencyPropertyKey for SortDirection property /// private static readonly DependencyPropertyKey SortDirectionPropertyKey = DependencyProperty.RegisterReadOnly( "SortDirection", typeof(Nullable), typeof(EGC.DataGridColumnHeader), new FrameworkPropertyMetadata(null, null, new CoerceValueCallback(OnCoerceSortDirection))); /// /// The DependencyProperty for the SortDirection property. /// public static readonly DependencyProperty SortDirectionProperty = SortDirectionPropertyKey.DependencyProperty; /// /// The property for current sort direction of the column of this header /// public Nullable SortDirection { get { return (Nullable)GetValue(SortDirectionProperty); } } /// /// The override of ButtonBase.OnClick. /// Informs the owning datagrid to sort itself after the execution of usual button stuff /// protected override void OnClick() { if (!SuppressClickEvent) { if (AutomationPeer.ListenerExists(AutomationEvents.InvokePatternOnInvoked)) { AutomationPeer peer = UIElementAutomationPeer.CreatePeerForElement(this); if (peer != null) { peer.RaiseAutomationEvent(AutomationEvents.InvokePatternOnInvoked); } } base.OnClick(); if (Column != null && Column.DataGridOwner != null) { Column.DataGridOwner.PerformSort(Column); } } } /// /// Coercion callback for Height property. /// private static object OnCoerceHeight(DependencyObject d, object baseValue) { var header = d as EGC.DataGridColumnHeader; EGC.DataGrid dataGrid = header.Column != null ? header.Column.DataGridOwner : null; return EGC.DataGridHelper.GetCoercedTransferPropertyValue( header, baseValue, HeightProperty, dataGrid, EGC.DataGrid.ColumnHeaderHeightProperty); } /// /// Coercion callback for CanUserSort property. Checks for the value of CanUserSort on owning column /// and returns accordingly /// private static object OnCoerceCanUserSort(DependencyObject d, object baseValue) { EGC.DataGridColumnHeader header = (EGC.DataGridColumnHeader)d; EGC.DataGridColumn column = header.Column; if (column != null) { return column.CanUserSort; } return baseValue; } /// /// Coercion callback for SortDirection property /// private static object OnCoerceSortDirection(DependencyObject d, object baseValue) { EGC.DataGridColumnHeader header = (EGC.DataGridColumnHeader)d; EGC.DataGridColumn column = header.Column; if (column != null) { return column.SortDirection; } return baseValue; } #endregion #region Automation protected override System.Windows.Automation.Peers.AutomationPeer OnCreateAutomationPeer() { return new EGC.DataGridColumnHeaderAutomationPeer(this); } // Called from DataGridColumnHeaderAutomationPeer internal void Invoke() { this.OnClick(); } #endregion #region Frozen Columns /// /// DependencyPropertyKey for IsFrozen property /// private static readonly DependencyPropertyKey IsFrozenPropertyKey = DependencyProperty.RegisterReadOnly( "IsFrozen", typeof(bool), typeof(EGC.DataGridColumnHeader), new FrameworkPropertyMetadata(false, null, new CoerceValueCallback(OnCoerceIsFrozen))); /// /// The DependencyProperty for the IsFrozen property. /// public static readonly DependencyProperty IsFrozenProperty = IsFrozenPropertyKey.DependencyProperty; /// /// The property to determine if the column corresponding to this header is frozen or not /// public bool IsFrozen { get { return (bool)GetValue(IsFrozenProperty); } } /// /// Coercion callback for IsFrozen property /// private static object OnCoerceIsFrozen(DependencyObject d, object baseValue) { EGC.DataGridColumnHeader header = (EGC.DataGridColumnHeader)d; EGC.DataGridColumn column = header.Column; if (column != null) { return column.IsFrozen; } return baseValue; } /// /// Coercion call back for clip property which ensures that the header overlapping with frozen /// column gets clipped appropriately. /// private static object OnCoerceClip(DependencyObject d, object baseValue) { EGC.DataGridColumnHeader header = (EGC.DataGridColumnHeader)d; Geometry geometry = baseValue as Geometry; Geometry frozenGeometry = EGC.DataGridHelper.GetFrozenClipForCell(header); if (frozenGeometry != null) { if (geometry == null) { return frozenGeometry; } geometry = new CombinedGeometry(GeometryCombineMode.Intersect, geometry, frozenGeometry); } return geometry; } #endregion #region Column Reordering internal EGC.DataGridColumnHeadersPresenter ParentPresenter { get { if (_parentPresenter == null) { _parentPresenter = ItemsControl.ItemsControlFromItemContainer(this) as EGC.DataGridColumnHeadersPresenter; } return _parentPresenter; } } /// /// Property which determines if click event has to raised or not. Used during column drag drop which could /// be mis-interpreted as a click /// internal bool SuppressClickEvent { get { return _suppressClickEvent; } set { _suppressClickEvent = value; } } protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e) { base.OnMouseLeftButtonDown(e); // If clickmode is hover then during the mouse move the hover events will be sent // all the headers in the path. To avoid that we are using a capture if (ClickMode == ClickMode.Hover && e.ButtonState == MouseButtonState.Pressed) { CaptureMouse(); } ParentPresenter.OnHeaderMouseLeftButtonDown(e); e.Handled = true; } protected override void OnMouseMove(MouseEventArgs e) { base.OnMouseMove(e); ParentPresenter.OnHeaderMouseMove(e); e.Handled = true; } protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e) { base.OnMouseLeftButtonUp(e); if (ClickMode == ClickMode.Hover && IsMouseCaptured) { ReleaseMouseCapture(); } ParentPresenter.OnHeaderMouseLeftButtonUp(e); e.Handled = true; } protected override void OnLostMouseCapture(MouseEventArgs e) { base.OnLostMouseCapture(e); ParentPresenter.OnHeaderLostMouseCapture(e); e.Handled = true; } #endregion #region Helpers EGC.DataGridColumn IProvideDataGridColumn.Column { get { return _column; } } private Panel ParentPanel { get { return VisualParent as Panel; } } /// /// Used by the resize code -- this is the header that the left gripper should be resizing. /// private EGC.DataGridColumnHeader PreviousHeader { get { // TODO: we need to be able to find the corner header too. EGC.DataGridColumn column = Column; if (column != null && column.DataGridOwner != null) { return column.DataGridOwner.ColumnHeaderFromDisplayIndex(column.DisplayIndex - 1); } return null; } } #endregion #region Data private EGC.DataGridColumn _column; private EGC.ContainerTracking _tracker; private EGC.DataGridColumnHeadersPresenter _parentPresenter; private Thumb _leftGripper, _rightGripper; private bool _suppressClickEvent; private const string LeftHeaderGripperTemplateName = "PART_LeftHeaderGripper"; private const string RightHeaderGripperTemplateName = "PART_RightHeaderGripper"; #endregion } }