Sic.Framework-Nanjing-Baishi/MECF.Framework.UI.Client/DataGridTransform/DataGrid/Microsoft/Windows/Controls/Primitives/DataGridColumnHeader.cs

952 lines
35 KiB
C#

//---------------------------------------------------------------------------
//
// 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
{
/// <summary>
/// Container for the Column header object. This is instantiated by the DataGridColumnHeadersPresenter.
/// </summary>
[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));
}
/// <summary>
/// Instantiates a new instance of this class.
/// </summary>
public DataGridColumnHeader()
{
_tracker = new EGC.ContainerTracking<EGC.DataGridColumnHeader>(this);
}
#endregion
#region Public API
/// <summary>
/// The Column associated with this DataGridColumnHeader.
/// </summary>
public EGC.DataGridColumn Column
{
get
{
return _column;
}
}
/// <summary>
/// Property that indicates the brush to use when drawing seperators between headers.
/// </summary>
public Brush SeparatorBrush
{
get { return (Brush)GetValue(SeparatorBrushProperty); }
set { SetValue(SeparatorBrushProperty, value); }
}
/// <summary>
/// DependencyProperty for SeperatorBrush.
/// </summary>
public static readonly DependencyProperty SeparatorBrushProperty =
DependencyProperty.Register("SeparatorBrush", typeof(Brush), typeof(EGC.DataGridColumnHeader), new FrameworkPropertyMetadata(null));
/// <summary>
/// Property that indicates the Visibility for the header seperators.
/// </summary>
public Visibility SeparatorVisibility
{
get { return (Visibility)GetValue(SeparatorVisibilityProperty); }
set { SetValue(SeparatorVisibilityProperty, value); }
}
/// <summary>
/// DependencyProperty for SeperatorBrush.
/// </summary>
public static readonly DependencyProperty SeparatorVisibilityProperty =
DependencyProperty.Register("SeparatorVisibility", typeof(Visibility), typeof(EGC.DataGridColumnHeader), new FrameworkPropertyMetadata(Visibility.Visible));
#endregion
#region Column Header Generation
/// <summary>
/// Prepares a column header to be used. Sets up the association between the column header and its column.
/// </summary>
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;
}
/// <summary>
/// Used by the DataGridRowGenerator owner to send notifications to the cell container.
/// </summary>
internal EGC.ContainerTracking<EGC.DataGridColumnHeader> Tracker
{
get { return _tracker; }
}
#endregion
#region Resize Gripper
/// <summary>
/// DependencyPropertyKey for DisplayIndex property
/// </summary>
private static readonly DependencyPropertyKey DisplayIndexPropertyKey =
DependencyProperty.RegisterReadOnly(
"DisplayIndex",
typeof(int),
typeof(EGC.DataGridColumnHeader),
new FrameworkPropertyMetadata(-1, new PropertyChangedCallback(OnDisplayIndexChanged), new CoerceValueCallback(OnCoerceDisplayIndex)));
/// <summary>
/// The DependencyProperty for the DisplayIndex property.
/// </summary>
public static readonly DependencyProperty DisplayIndexProperty = DisplayIndexPropertyKey.DependencyProperty;
/// <summary>
/// The property which represents the displayindex of the column corresponding to this header
/// </summary>
public int DisplayIndex
{
get { return (int)GetValue(DisplayIndexProperty); }
}
/// <summary>
/// Coercion callback for DisplayIndex property
/// </summary>
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;
}
/// <summary>
/// Property changed call back for DisplayIndex property.
/// Sets the visibility of resize grippers accordingly
/// </summary>
/// <param name="d"></param>
/// <param name="e"></param>
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);
}
}
}
}
/// <summary>
/// Override for <see cref="System.Windows.FrameworkElement.OnApplyTemplate">FrameworkElement.OnApplyTemplate</see>
/// </summary>
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
HookupGripperEvents();
}
/// <summary>
/// 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.
/// </summary>
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();
}
}
/// <summary>
/// Clear gripper event
/// </summary>
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;
}
}
/// <summary>
/// Returns either this header or the one before it depending on which Gripper fired the event.
/// </summary>
/// <param name="sender"></param>
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;
}
}
/// <summary>
/// Method which recomputes the widths of columns on resize of a header
/// </summary>
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
/// <summary>
/// Notifies the Header of a property change.
/// </summary>
private static void OnNotifyPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((EGC.DataGridColumnHeader)d).NotifyPropertyChanged(d, e);
}
/// <summary>
/// Notification for column header-related DependencyProperty changes from the grid or from columns.
/// </summary>
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
/// <summary>
/// Coerces the Content property. We're choosing a value between Column.Header and the Content property on ColumnHeader.
/// </summary>
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);
}
/// <summary>
/// Coerces the ContentTemplate property based on the templates defined on the Column.
/// </summary>
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);
}
/// <summary>
/// Coerces the ContentTemplateSelector property based on the selector defined on the Column.
/// </summary>
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);
}
/// <summary>
/// Coerces the ContentStringFormat property based on the templates defined on the Column.
/// </summary>
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);
}
/// <summary>
/// Coerces the Style property based on the templates defined on the Column or DataGrid.
/// </summary>
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
/// <summary>
/// DependencyPropertyKey for CanUserSort property
/// </summary>
private static readonly DependencyPropertyKey CanUserSortPropertyKey =
DependencyProperty.RegisterReadOnly(
"CanUserSort",
typeof(bool),
typeof(EGC.DataGridColumnHeader),
new FrameworkPropertyMetadata(true, null, new CoerceValueCallback(OnCoerceCanUserSort)));
/// <summary>
/// The DependencyProperty for the CanUserSort property.
/// </summary>
public static readonly DependencyProperty CanUserSortProperty = CanUserSortPropertyKey.DependencyProperty;
/// <summary>
/// CanUserSort is the flag which determines if the datagrid can be sorted based on the column of this header
/// </summary>
public bool CanUserSort
{
get { return (bool)GetValue(CanUserSortProperty); }
}
/// <summary>
/// DependencyPropertyKey for SortDirection property
/// </summary>
private static readonly DependencyPropertyKey SortDirectionPropertyKey =
DependencyProperty.RegisterReadOnly(
"SortDirection",
typeof(Nullable<ListSortDirection>),
typeof(EGC.DataGridColumnHeader),
new FrameworkPropertyMetadata(null, null, new CoerceValueCallback(OnCoerceSortDirection)));
/// <summary>
/// The DependencyProperty for the SortDirection property.
/// </summary>
public static readonly DependencyProperty SortDirectionProperty = SortDirectionPropertyKey.DependencyProperty;
/// <summary>
/// The property for current sort direction of the column of this header
/// </summary>
public Nullable<ListSortDirection> SortDirection
{
get { return (Nullable<ListSortDirection>)GetValue(SortDirectionProperty); }
}
/// <summary>
/// The override of ButtonBase.OnClick.
/// Informs the owning datagrid to sort itself after the execution of usual button stuff
/// </summary>
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);
}
}
}
/// <summary>
/// Coercion callback for Height property.
/// </summary>
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);
}
/// <summary>
/// Coercion callback for CanUserSort property. Checks for the value of CanUserSort on owning column
/// and returns accordingly
/// </summary>
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;
}
/// <summary>
/// Coercion callback for SortDirection property
/// </summary>
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
/// <summary>
/// DependencyPropertyKey for IsFrozen property
/// </summary>
private static readonly DependencyPropertyKey IsFrozenPropertyKey =
DependencyProperty.RegisterReadOnly(
"IsFrozen",
typeof(bool),
typeof(EGC.DataGridColumnHeader),
new FrameworkPropertyMetadata(false, null, new CoerceValueCallback(OnCoerceIsFrozen)));
/// <summary>
/// The DependencyProperty for the IsFrozen property.
/// </summary>
public static readonly DependencyProperty IsFrozenProperty = IsFrozenPropertyKey.DependencyProperty;
/// <summary>
/// The property to determine if the column corresponding to this header is frozen or not
/// </summary>
public bool IsFrozen
{
get { return (bool)GetValue(IsFrozenProperty); }
}
/// <summary>
/// Coercion callback for IsFrozen property
/// </summary>
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;
}
/// <summary>
/// Coercion call back for clip property which ensures that the header overlapping with frozen
/// column gets clipped appropriately.
/// </summary>
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;
}
}
/// <summary>
/// Property which determines if click event has to raised or not. Used during column drag drop which could
/// be mis-interpreted as a click
/// </summary>
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;
}
}
/// <summary>
/// Used by the resize code -- this is the header that the left gripper should be resizing.
/// </summary>
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<EGC.DataGridColumnHeader> _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
}
}