Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / System / Windows / Controls / DataGridCell.cs / 1305600 / DataGridCell.cs
//---------------------------------------------------------------------------- // // Copyright (C) Microsoft Corporation. All rights reserved. // //--------------------------------------------------------------------------- using System; using System.Collections.ObjectModel; using System.ComponentModel; using System.Diagnostics; using System.Globalization; using System.Windows; using System.Windows.Controls.Primitives; using System.Windows.Data; using System.Windows.Input; using System.Windows.Media; using System.Windows.Threading; namespace System.Windows.Controls { ////// A control for displaying a cell of the DataGrid. /// public class DataGridCell : ContentControl, IProvideDataGridColumn { #region Constructors ////// Instantiates global information. /// static DataGridCell() { DefaultStyleKeyProperty.OverrideMetadata(typeof(DataGridCell), new FrameworkPropertyMetadata(typeof(DataGridCell))); StyleProperty.OverrideMetadata(typeof(DataGridCell), new FrameworkPropertyMetadata(null, OnNotifyPropertyChanged, OnCoerceStyle)); ClipProperty.OverrideMetadata(typeof(DataGridCell), new FrameworkPropertyMetadata(null, new CoerceValueCallback(OnCoerceClip))); KeyboardNavigation.TabNavigationProperty.OverrideMetadata(typeof(DataGridCell), new FrameworkPropertyMetadata(KeyboardNavigationMode.Local)); // Set SnapsToDevicePixels to true so that this element can draw grid lines. The metadata options are so that the property value doesn't inherit down the tree from here. SnapsToDevicePixelsProperty.OverrideMetadata(typeof(DataGridCell), new FrameworkPropertyMetadata(true, FrameworkPropertyMetadataOptions.AffectsArrange)); EventManager.RegisterClassHandler(typeof(DataGridCell), MouseLeftButtonDownEvent, new MouseButtonEventHandler(OnAnyMouseLeftButtonDownThunk), true); IsMouseOverPropertyKey.OverrideMetadata(typeof(DataGridCell), new UIPropertyMetadata(new PropertyChangedCallback(OnVisualStatePropertyChanged))); EventManager.RegisterClassHandler(typeof(DataGridCell), LostFocusEvent, new RoutedEventHandler(OnAnyLostFocus), true); EventManager.RegisterClassHandler(typeof(DataGridCell), GotFocusEvent, new RoutedEventHandler(OnAnyGotFocus), true); } ////// Instantiates a new instance of this class. /// public DataGridCell() { _tracker = new ContainerTracking(this); } #endregion #region Automation protected override System.Windows.Automation.Peers.AutomationPeer OnCreateAutomationPeer() { return new System.Windows.Automation.Peers.DataGridCellAutomationPeer(this); } #endregion #region Cell Generation /// /// Prepares a cell for use. /// ////// Updates the column reference. /// This overload computes the column index from the ItemContainerGenerator. /// internal void PrepareCell(object item, ItemsControl cellsPresenter, DataGridRow ownerRow) { PrepareCell(item, ownerRow, cellsPresenter.ItemContainerGenerator.IndexFromContainer(this)); } ////// Prepares a cell for use. /// ////// Updates the column reference. /// internal void PrepareCell(object item, DataGridRow ownerRow, int index) { Debug.Assert(_owner == null || _owner == ownerRow, "_owner should be null before PrepareCell is called or the same value as the ownerRow."); _owner = ownerRow; DataGrid dataGrid = _owner.DataGridOwner; if (dataGrid != null) { // The index of the container should correspond to the index of the column if ((index >= 0) && (index < dataGrid.Columns.Count)) { // Retrieve the column definition and pass it to the cell container DataGridColumn column = dataGrid.Columns[index]; Column = column; TabIndex = column.DisplayIndex; } if (IsEditing) { // If IsEditing was left on and this container was recycled, reset it here. // Setting this property will result in BuildVisualTree being called. IsEditing = false; } else if ((Content as FrameworkElement) == null) { // If there isn't already a visual tree, then create one. BuildVisualTree(); if (!NeedsVisualTree) { Content = item; } } // Update cell Selection bool isSelected = dataGrid.SelectedCellsInternal.Contains(this); SyncIsSelected(isSelected); } DataGridHelper.TransferProperty(this, StyleProperty); DataGridHelper.TransferProperty(this, IsReadOnlyProperty); CoerceValue(ClipProperty); } ////// Clears the cell of references. /// internal void ClearCell(DataGridRow ownerRow) { Debug.Assert(_owner == ownerRow, "_owner should be the same as the DataGridRow that is clearing the cell."); _owner = null; } ////// Used by the DataGridRowGenerator owner to send notifications to the cell container. /// internal ContainerTrackingTracker { get { return _tracker; } } #endregion #region Column Information /// /// The column that defines how this cell should appear. /// public DataGridColumn Column { get { return (DataGridColumn)GetValue(ColumnProperty); } internal set { SetValue(ColumnPropertyKey, value); } } ////// The DependencyPropertyKey that allows writing the Column property value. /// private static readonly DependencyPropertyKey ColumnPropertyKey = DependencyProperty.RegisterReadOnly("Column", typeof(DataGridColumn), typeof(DataGridCell), new FrameworkPropertyMetadata(null, new PropertyChangedCallback(OnColumnChanged))); ////// The DependencyProperty for the Columns property. /// public static readonly DependencyProperty ColumnProperty = ColumnPropertyKey.DependencyProperty; ////// Called when the Column property changes. /// Calls the protected virtual OnColumnChanged. /// private static void OnColumnChanged(object sender, DependencyPropertyChangedEventArgs e) { DataGridCell cell = sender as DataGridCell; if (cell != null) { cell.OnColumnChanged((DataGridColumn)e.OldValue, (DataGridColumn)e.NewValue); } } ////// Called due to the cell's column definition changing. /// Not called due to changes within the current column definition. /// ////// Coerces ContentTemplate and ContentTemplateSelector. /// /// The old column definition. /// The new column definition. protected virtual void OnColumnChanged(DataGridColumn oldColumn, DataGridColumn newColumn) { // We need to call BuildVisualTree after changing the column (PrepareCell does this). Content = null; DataGridHelper.TransferProperty(this, StyleProperty); DataGridHelper.TransferProperty(this, IsReadOnlyProperty); } #endregion #region Notification Propagation ////// Notifies the Cell of a property change. /// private static void OnNotifyPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ((DataGridCell)d).NotifyPropertyChanged(d, string.Empty, e, DataGridNotificationTarget.Cells); } ////// Cancels editing the current cell & notifies the cell of a change to IsReadOnly. /// private static void OnNotifyIsReadOnlyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var cell = (DataGridCell)d; var dataGrid = cell.DataGridOwner; if ((bool)e.NewValue && dataGrid != null) { dataGrid.CancelEdit(cell); } // re-evalutate the BeginEdit command's CanExecute. CommandManager.InvalidateRequerySuggested(); cell.NotifyPropertyChanged(d, string.Empty, e, DataGridNotificationTarget.Cells); } ////// General notification for DependencyProperty changes from the grid or from columns. /// internal void NotifyPropertyChanged(DependencyObject d, string propertyName, DependencyPropertyChangedEventArgs e, DataGridNotificationTarget target) { DataGridColumn column = d as DataGridColumn; if ((column != null) && (column != Column)) { // This notification does not apply to this cell return; } // All the notifications which are to be handled by the cell if (DataGridHelper.ShouldNotifyCells(target)) { if (e.Property == DataGridColumn.WidthProperty) { DataGridHelper.OnColumnWidthChanged(this, e); } else if (e.Property == DataGrid.CellStyleProperty || e.Property == DataGridColumn.CellStyleProperty || e.Property == StyleProperty) { DataGridHelper.TransferProperty(this, StyleProperty); } else if (e.Property == DataGrid.IsReadOnlyProperty || e.Property == DataGridColumn.IsReadOnlyProperty || e.Property == IsReadOnlyProperty) { DataGridHelper.TransferProperty(this, IsReadOnlyProperty); } else if (e.Property == DataGridColumn.DisplayIndexProperty) { TabIndex = column.DisplayIndex; } else if (e.Property == DataGrid.IsKeyboardFocusWithinProperty) { UpdateVisualState(); } } // All the notifications which needs forward to columns if (DataGridHelper.ShouldRefreshCellContent(target)) { if (column != null && NeedsVisualTree) { if (!string.IsNullOrEmpty(propertyName)) { column.RefreshCellContent(this, propertyName); } else if (e != null && e.Property != null) { column.RefreshCellContent(this, e.Property.Name); } } } } #endregion #region Style private static object OnCoerceStyle(DependencyObject d, object baseValue) { var cell = d as DataGridCell; return DataGridHelper.GetCoercedTransferPropertyValue( cell, baseValue, StyleProperty, cell.Column, DataGridColumn.CellStyleProperty, cell.DataGridOwner, DataGrid.CellStyleProperty); } #endregion #region Template internal override void ChangeVisualState(bool useTransitions) { if (DataGridOwner == null) { return; } // CommonStates if (IsMouseOver) { VisualStates.GoToState(this, useTransitions, VisualStates.StateMouseOver, VisualStates.StateNormal); } else { VisualStateManager.GoToState(this, VisualStates.StateNormal, useTransitions); } // SelectionStates if (IsSelected) { VisualStates.GoToState(this, useTransitions, VisualStates.StateSelected, VisualStates.StateUnselected); } else { VisualStates.GoToState(this, useTransitions, VisualStates.StateUnselected); } // FocusStates if (DataGridOwner.IsKeyboardFocusWithin) { VisualStates.GoToState(this, useTransitions, VisualStates.StateFocused, VisualStates.StateUnfocused); } else { VisualStateManager.GoToState(this, VisualStates.StateUnfocused, useTransitions); } // CurrentStates if (IsCurrent) { VisualStates.GoToState(this, useTransitions, VisualStates.StateCurrent, VisualStates.StateRegular); } else { VisualStateManager.GoToState(this, VisualStates.StateRegular, useTransitions); } // Interaction states if (IsEditing) { VisualStates.GoToState(this, useTransitions, VisualStates.StateEditing, VisualStates.StateDisplay); } else { VisualStateManager.GoToState(this, VisualStates.StateDisplay, useTransitions); } base.ChangeVisualState(useTransitions); } ////// Builds a column's visual tree if not using templates. /// internal void BuildVisualTree() { if (NeedsVisualTree) { var column = Column; if (column != null) { // Work around a problem with BindingGroup not removing BindingExpressions. var row = RowOwner; if (row != null) { var bindingGroup = row.BindingGroup; if (bindingGroup != null) { RemoveBindingExpressions(bindingGroup, Content as DependencyObject); } } // Ask the column to build a visual tree and // hook the visual tree up through the Content property. Content = column.BuildVisualTree(IsEditing, RowDataItem, this); } } } private void RemoveBindingExpressions(BindingGroup bindingGroup, DependencyObject element) { if (element == null) return; // no content, hence no bindings to remove var bindingExpressions = bindingGroup.BindingExpressions; for (int i = 0; i < bindingExpressions.Count; i++) { if (VisualTreeHelper.IsAncestorOf(element, bindingExpressions[i].TargetElement, typeof(DataGridCell))) { bindingExpressions.RemoveAt(i--); } } } #endregion #region Editing ////// Whether the cell is in editing mode. /// public bool IsEditing { get { return (bool)GetValue(IsEditingProperty); } set { SetValue(IsEditingProperty, value); } } ////// Represents the IsEditing property. /// public static readonly DependencyProperty IsEditingProperty = DependencyProperty.Register("IsEditing", typeof(bool), typeof(DataGridCell), new FrameworkPropertyMetadata(false, new PropertyChangedCallback(OnIsEditingChanged))); private static void OnIsEditingChanged(object sender, DependencyPropertyChangedEventArgs e) { ((DataGridCell)sender).OnIsEditingChanged((bool)e.NewValue); } ////// Called when the value of IsEditing changes. /// ////// Coerces the value of ContentTemplate. /// /// The new value of IsEditing. protected virtual void OnIsEditingChanged(bool isEditing) { if (IsKeyboardFocusWithin && !IsKeyboardFocused) { // Keep focus on the cell when flipping modes Focus(); } // If templates aren't being used, then a new visual tree needs to be built. BuildVisualTree(); UpdateVisualState(); } internal void NotifyCurrentCellContainerChanged() { UpdateVisualState(); } ////// Whether the cell is the current cell. /// private bool IsCurrent { get { var row = RowOwner; var column = Column; if (row != null && column != null) { var dataGrid = row.DataGridOwner; if (dataGrid != null) { return dataGrid.CurrentItem == row.Item && dataGrid.CurrentColumn == column; } } return false; } } ////// Whether the cell can be placed in edit mode. /// public bool IsReadOnly { get { return (bool)GetValue(IsReadOnlyProperty); } } private static readonly DependencyPropertyKey IsReadOnlyPropertyKey = DependencyProperty.RegisterReadOnly("IsReadOnly", typeof(bool), typeof(DataGridCell), new FrameworkPropertyMetadata(false, OnNotifyIsReadOnlyChanged, OnCoerceIsReadOnly)); ////// The DependencyProperty for IsReadOnly. /// public static readonly DependencyProperty IsReadOnlyProperty = IsReadOnlyPropertyKey.DependencyProperty; private static object OnCoerceIsReadOnly(DependencyObject d, object baseValue) { var cell = d as DataGridCell; var column = cell.Column; var dataGrid = cell.DataGridOwner; // We dont use the cell & 'baseValue' here because this property is read only on cell. // the column may coerce a default value to 'true', so we'll use it's effective value for IsReadOnly // as the baseValue. return DataGridHelper.GetCoercedTransferPropertyValue( column, column.IsReadOnly, DataGridColumn.IsReadOnlyProperty, dataGrid, DataGrid.IsReadOnlyProperty); } private static void OnAnyLostFocus(object sender, RoutedEventArgs e) { // Get the ancestor cell of old focused element. // Set DataGrid.FocusedCell to null, if the cell doesn't // have keyboard focus. DataGridCell cell = DataGridHelper.FindVisualParent(e.OriginalSource as UIElement); if (cell != null && cell == sender) { DataGrid owner = cell.DataGridOwner; if (owner != null && !cell.IsKeyboardFocusWithin && owner.FocusedCell == cell) { owner.FocusedCell = null; } } } private static void OnAnyGotFocus(object sender, RoutedEventArgs e) { DataGridCell cell = DataGridHelper.FindVisualParent (e.OriginalSource as UIElement); if (cell != null && cell == sender) { DataGrid owner = cell.DataGridOwner; if (owner != null) { owner.FocusedCell = cell; } } } internal void BeginEdit(RoutedEventArgs e) { Debug.Assert(!IsEditing, "Should not call BeginEdit when IsEditing is true."); IsEditing = true; DataGridColumn column = Column; if (column != null) { // Ask the column to store the original value column.BeginEdit(Content as FrameworkElement, e); } RaisePreparingCellForEdit(e); } internal void CancelEdit() { Debug.Assert(IsEditing, "Should not call CancelEdit when IsEditing is false."); DataGridColumn column = Column; if (column != null) { // Ask the column to restore the original value column.CancelEdit(Content as FrameworkElement); } IsEditing = false; } internal bool CommitEdit() { Debug.Assert(IsEditing, "Should not call CommitEdit when IsEditing is false."); bool validationPassed = true; DataGridColumn column = Column; if (column != null) { // Ask the column to access the binding and update the data source // If validation fails, then remain in editing mode validationPassed = column.CommitEdit(Content as FrameworkElement); } if (validationPassed) { IsEditing = false; } return validationPassed; } private void RaisePreparingCellForEdit(RoutedEventArgs editingEventArgs) { DataGrid dataGridOwner = DataGridOwner; if (dataGridOwner != null) { FrameworkElement currentEditingElement = EditingElement; DataGridPreparingCellForEditEventArgs preparingCellForEditEventArgs = new DataGridPreparingCellForEditEventArgs(Column, RowOwner, editingEventArgs, currentEditingElement); dataGridOwner.OnPreparingCellForEdit(preparingCellForEditEventArgs); } } internal FrameworkElement EditingElement { get { // The editing element was stored in the Content property. return Content as FrameworkElement; } } #endregion #region Selection /// /// Whether the cell is selected or not. /// public bool IsSelected { get { return (bool)GetValue(IsSelectedProperty); } set { SetValue(IsSelectedProperty, value); } } ////// Represents the IsSelected property. /// public static readonly DependencyProperty IsSelectedProperty = DependencyProperty.Register("IsSelected", typeof(bool), typeof(DataGridCell), new FrameworkPropertyMetadata(false, new PropertyChangedCallback(OnIsSelectedChanged))); private static void OnIsSelectedChanged(object sender, DependencyPropertyChangedEventArgs e) { DataGridCell cell = (DataGridCell)sender; bool isSelected = (bool)e.NewValue; // There is no reason to notify the DataGrid if IsSelected's value came // from the DataGrid. if (!cell._syncingIsSelected) { DataGrid dataGrid = cell.DataGridOwner; if (dataGrid != null) { // Notify the DataGrid that a cell's IsSelected property changed // in case it was done programmatically instead of by the // DataGrid itself. dataGrid.CellIsSelectedChanged(cell, isSelected); } } cell.RaiseSelectionChangedEvent(isSelected); cell.UpdateVisualState(); } ////// Used to synchronize IsSelected with the DataGrid. /// Prevents unncessary notification back to the DataGrid. /// internal void SyncIsSelected(bool isSelected) { bool originalValue = _syncingIsSelected; _syncingIsSelected = true; try { IsSelected = isSelected; } finally { _syncingIsSelected = originalValue; } } private void RaiseSelectionChangedEvent(bool isSelected) { if (isSelected) { OnSelected(new RoutedEventArgs(SelectedEvent, this)); } else { OnUnselected(new RoutedEventArgs(UnselectedEvent, this)); } } ////// Raised when the item's IsSelected property becomes true. /// public static readonly RoutedEvent SelectedEvent = EventManager.RegisterRoutedEvent("Selected", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(DataGridCell)); ////// Raised when the item's IsSelected property becomes true. /// public event RoutedEventHandler Selected { add { AddHandler(SelectedEvent, value); } remove { RemoveHandler(SelectedEvent, value); } } ////// Called when IsSelected becomes true. Raises the Selected event. /// /// Empty event arguments. protected virtual void OnSelected(RoutedEventArgs e) { RaiseEvent(e); } ////// Raised when the item's IsSelected property becomes false. /// public static readonly RoutedEvent UnselectedEvent = EventManager.RegisterRoutedEvent("Unselected", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(DataGridCell)); ////// Raised when the item's IsSelected property becomes false. /// public event RoutedEventHandler Unselected { add { AddHandler(UnselectedEvent, value); } remove { RemoveHandler(UnselectedEvent, value); } } ////// Called when IsSelected becomes false. Raises the Unselected event. /// /// Empty event arguments. protected virtual void OnUnselected(RoutedEventArgs e) { RaiseEvent(e); } #endregion #region GridLines // Different parts of the DataGrid draw different pieces of the GridLines. // Cells draw a single line on their right side. ////// Measure. This is overridden so that the cell can extend its size to account for a grid line on the right. /// protected override Size MeasureOverride(Size constraint) { // Make space for the GridLine on the right: // Remove space from the constraint (since it implicitly includes the GridLine's thickness), // call the base implementation, and add the thickness back for the returned size. if (DataGridHelper.IsGridLineVisible(DataGridOwner, /*isHorizontal = */ false)) { double thickness = DataGridOwner.VerticalGridLineThickness; Size desiredSize = base.MeasureOverride(DataGridHelper.SubtractFromSize(constraint, thickness, /*height = */ false)); desiredSize.Width += thickness; return desiredSize; } else { return base.MeasureOverride(constraint); } } ////// Arrange. This is overriden so that the cell can position its content to account for a grid line on the right. /// /// Arrange size protected override Size ArrangeOverride(Size arrangeSize) { // We don't need to adjust the Arrange position of the content. By default it is arranged at 0,0 and we're // adding a line to the right. All we have to do is compress and extend the size, just like Measure. if (DataGridHelper.IsGridLineVisible(DataGridOwner, /*isHorizontal = */ false)) { double thickness = DataGridOwner.VerticalGridLineThickness; Size returnSize = base.ArrangeOverride(DataGridHelper.SubtractFromSize(arrangeSize, thickness, /*height = */ false)); returnSize.Width += thickness; return returnSize; } else { return base.ArrangeOverride(arrangeSize); } } ////// OnRender. Overriden to draw a vertical line on the right. /// /// protected override void OnRender(DrawingContext drawingContext) { base.OnRender(drawingContext); if (DataGridHelper.IsGridLineVisible(DataGridOwner, /*isHorizontal = */ false)) { double thickness = DataGridOwner.VerticalGridLineThickness; Rect rect = new Rect(new Size(thickness, RenderSize.Height)); rect.X = RenderSize.Width - thickness; drawingContext.DrawRectangle(DataGridOwner.VerticalGridLinesBrush, null, rect); } } #endregion #region Input private static void OnAnyMouseLeftButtonDownThunk(object sender, MouseButtonEventArgs e) { ((DataGridCell)sender).OnAnyMouseLeftButtonDown(e); } ////// The left mouse button was pressed /// /// private void OnAnyMouseLeftButtonDown(MouseButtonEventArgs e) { bool focusWithin = IsKeyboardFocusWithin; bool isCtrlKeyPressed = (Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control; if (focusWithin && !isCtrlKeyPressed && !e.Handled && !IsEditing && !IsReadOnly && IsSelected) { // The cell is focused and there are no other special selection gestures, // enter edit mode. DataGrid dataGridOwner = DataGridOwner; if (dataGridOwner != null) { // The cell was clicked, which means that other cells may // need to be de-selected, let the DataGrid handle that. dataGridOwner.HandleSelectionForCellInput(this, /* startDragging = */ false, /* allowsExtendSelect = */ true, /* allowsMinimalSelect = */ false); // Enter edit mode dataGridOwner.BeginEdit(e); e.Handled = true; } } else if (!focusWithin || !IsSelected || isCtrlKeyPressed) { if (!focusWithin) { // The cell should receive focus on click Focus(); } DataGrid dataGridOwner = DataGridOwner; if (dataGridOwner != null) { // Let the DataGrid process selection dataGridOwner.HandleSelectionForCellInput(this, /* startDragging = */ Mouse.Captured == null, /* allowsExtendSelect = */ true, /* allowsMinimalSelect = */ true); } e.Handled = true; } #if PUBLIC_ONINPUT else { SendInputToColumn(e); } #endif } ////// Reporting text composition. /// protected override void OnTextInput(TextCompositionEventArgs e) { SendInputToColumn(e); } ////// Reporting a key was pressed. /// protected override void OnKeyDown(KeyEventArgs e) { SendInputToColumn(e); } #if PUBLIC_ONINPUT // ////// Reporting a key was released /// protected override void OnKeyUp(KeyEventArgs e) { SendInputToColumn(e); } ////// Reporting the mouse button was released /// protected override void OnMouseUp(MouseButtonEventArgs e) { SendInputToColumn(e); } #endif private void SendInputToColumn(InputEventArgs e) { var column = Column; if (column != null) { column.OnInput(e); } } #endregion #region Frozen Columns ////// Coercion call back for clip property which ensures that the cell overlapping with frozen /// column gets clipped appropriately. /// /// /// ///private static object OnCoerceClip(DependencyObject d, object baseValue) { DataGridCell cell = (DataGridCell)d; Geometry geometry = baseValue as Geometry; Geometry frozenGeometry = DataGridHelper.GetFrozenClipForCell(cell); if (frozenGeometry != null) { if (geometry == null) { return frozenGeometry; } geometry = new CombinedGeometry(GeometryCombineMode.Intersect, geometry, frozenGeometry); } return geometry; } #endregion #region Helpers internal DataGrid DataGridOwner { get { if (_owner != null) { DataGrid dataGridOwner = _owner.DataGridOwner; if (dataGridOwner == null) { dataGridOwner = ItemsControl.ItemsControlFromItemContainer(_owner) as DataGrid; } return dataGridOwner; } return null; } } private Panel ParentPanel { get { return VisualParent as Panel; } } internal DataGridRow RowOwner { get { return _owner; } } internal object RowDataItem { get { DataGridRow row = RowOwner; if (row != null) { return row.Item; } return DataContext; } } private DataGridCellsPresenter CellsPresenter { get { return ItemsControl.ItemsControlFromItemContainer(this) as DataGridCellsPresenter; } } private bool NeedsVisualTree { get { return (ContentTemplate == null) && (ContentTemplateSelector == null); } } #endregion #region Data private DataGridRow _owner; private ContainerTracking _tracker; private bool _syncingIsSelected; // Used to prevent unnecessary notifications #endregion } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved. //---------------------------------------------------------------------------- // // Copyright (C) Microsoft Corporation. All rights reserved. // //--------------------------------------------------------------------------- using System; using System.Collections.ObjectModel; using System.ComponentModel; using System.Diagnostics; using System.Globalization; using System.Windows; using System.Windows.Controls.Primitives; using System.Windows.Data; using System.Windows.Input; using System.Windows.Media; using System.Windows.Threading; namespace System.Windows.Controls { /// /// A control for displaying a cell of the DataGrid. /// public class DataGridCell : ContentControl, IProvideDataGridColumn { #region Constructors ////// Instantiates global information. /// static DataGridCell() { DefaultStyleKeyProperty.OverrideMetadata(typeof(DataGridCell), new FrameworkPropertyMetadata(typeof(DataGridCell))); StyleProperty.OverrideMetadata(typeof(DataGridCell), new FrameworkPropertyMetadata(null, OnNotifyPropertyChanged, OnCoerceStyle)); ClipProperty.OverrideMetadata(typeof(DataGridCell), new FrameworkPropertyMetadata(null, new CoerceValueCallback(OnCoerceClip))); KeyboardNavigation.TabNavigationProperty.OverrideMetadata(typeof(DataGridCell), new FrameworkPropertyMetadata(KeyboardNavigationMode.Local)); // Set SnapsToDevicePixels to true so that this element can draw grid lines. The metadata options are so that the property value doesn't inherit down the tree from here. SnapsToDevicePixelsProperty.OverrideMetadata(typeof(DataGridCell), new FrameworkPropertyMetadata(true, FrameworkPropertyMetadataOptions.AffectsArrange)); EventManager.RegisterClassHandler(typeof(DataGridCell), MouseLeftButtonDownEvent, new MouseButtonEventHandler(OnAnyMouseLeftButtonDownThunk), true); IsMouseOverPropertyKey.OverrideMetadata(typeof(DataGridCell), new UIPropertyMetadata(new PropertyChangedCallback(OnVisualStatePropertyChanged))); EventManager.RegisterClassHandler(typeof(DataGridCell), LostFocusEvent, new RoutedEventHandler(OnAnyLostFocus), true); EventManager.RegisterClassHandler(typeof(DataGridCell), GotFocusEvent, new RoutedEventHandler(OnAnyGotFocus), true); } ////// Instantiates a new instance of this class. /// public DataGridCell() { _tracker = new ContainerTracking(this); } #endregion #region Automation protected override System.Windows.Automation.Peers.AutomationPeer OnCreateAutomationPeer() { return new System.Windows.Automation.Peers.DataGridCellAutomationPeer(this); } #endregion #region Cell Generation /// /// Prepares a cell for use. /// ////// Updates the column reference. /// This overload computes the column index from the ItemContainerGenerator. /// internal void PrepareCell(object item, ItemsControl cellsPresenter, DataGridRow ownerRow) { PrepareCell(item, ownerRow, cellsPresenter.ItemContainerGenerator.IndexFromContainer(this)); } ////// Prepares a cell for use. /// ////// Updates the column reference. /// internal void PrepareCell(object item, DataGridRow ownerRow, int index) { Debug.Assert(_owner == null || _owner == ownerRow, "_owner should be null before PrepareCell is called or the same value as the ownerRow."); _owner = ownerRow; DataGrid dataGrid = _owner.DataGridOwner; if (dataGrid != null) { // The index of the container should correspond to the index of the column if ((index >= 0) && (index < dataGrid.Columns.Count)) { // Retrieve the column definition and pass it to the cell container DataGridColumn column = dataGrid.Columns[index]; Column = column; TabIndex = column.DisplayIndex; } if (IsEditing) { // If IsEditing was left on and this container was recycled, reset it here. // Setting this property will result in BuildVisualTree being called. IsEditing = false; } else if ((Content as FrameworkElement) == null) { // If there isn't already a visual tree, then create one. BuildVisualTree(); if (!NeedsVisualTree) { Content = item; } } // Update cell Selection bool isSelected = dataGrid.SelectedCellsInternal.Contains(this); SyncIsSelected(isSelected); } DataGridHelper.TransferProperty(this, StyleProperty); DataGridHelper.TransferProperty(this, IsReadOnlyProperty); CoerceValue(ClipProperty); } ////// Clears the cell of references. /// internal void ClearCell(DataGridRow ownerRow) { Debug.Assert(_owner == ownerRow, "_owner should be the same as the DataGridRow that is clearing the cell."); _owner = null; } ////// Used by the DataGridRowGenerator owner to send notifications to the cell container. /// internal ContainerTrackingTracker { get { return _tracker; } } #endregion #region Column Information /// /// The column that defines how this cell should appear. /// public DataGridColumn Column { get { return (DataGridColumn)GetValue(ColumnProperty); } internal set { SetValue(ColumnPropertyKey, value); } } ////// The DependencyPropertyKey that allows writing the Column property value. /// private static readonly DependencyPropertyKey ColumnPropertyKey = DependencyProperty.RegisterReadOnly("Column", typeof(DataGridColumn), typeof(DataGridCell), new FrameworkPropertyMetadata(null, new PropertyChangedCallback(OnColumnChanged))); ////// The DependencyProperty for the Columns property. /// public static readonly DependencyProperty ColumnProperty = ColumnPropertyKey.DependencyProperty; ////// Called when the Column property changes. /// Calls the protected virtual OnColumnChanged. /// private static void OnColumnChanged(object sender, DependencyPropertyChangedEventArgs e) { DataGridCell cell = sender as DataGridCell; if (cell != null) { cell.OnColumnChanged((DataGridColumn)e.OldValue, (DataGridColumn)e.NewValue); } } ////// Called due to the cell's column definition changing. /// Not called due to changes within the current column definition. /// ////// Coerces ContentTemplate and ContentTemplateSelector. /// /// The old column definition. /// The new column definition. protected virtual void OnColumnChanged(DataGridColumn oldColumn, DataGridColumn newColumn) { // We need to call BuildVisualTree after changing the column (PrepareCell does this). Content = null; DataGridHelper.TransferProperty(this, StyleProperty); DataGridHelper.TransferProperty(this, IsReadOnlyProperty); } #endregion #region Notification Propagation ////// Notifies the Cell of a property change. /// private static void OnNotifyPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ((DataGridCell)d).NotifyPropertyChanged(d, string.Empty, e, DataGridNotificationTarget.Cells); } ////// Cancels editing the current cell & notifies the cell of a change to IsReadOnly. /// private static void OnNotifyIsReadOnlyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var cell = (DataGridCell)d; var dataGrid = cell.DataGridOwner; if ((bool)e.NewValue && dataGrid != null) { dataGrid.CancelEdit(cell); } // re-evalutate the BeginEdit command's CanExecute. CommandManager.InvalidateRequerySuggested(); cell.NotifyPropertyChanged(d, string.Empty, e, DataGridNotificationTarget.Cells); } ////// General notification for DependencyProperty changes from the grid or from columns. /// internal void NotifyPropertyChanged(DependencyObject d, string propertyName, DependencyPropertyChangedEventArgs e, DataGridNotificationTarget target) { DataGridColumn column = d as DataGridColumn; if ((column != null) && (column != Column)) { // This notification does not apply to this cell return; } // All the notifications which are to be handled by the cell if (DataGridHelper.ShouldNotifyCells(target)) { if (e.Property == DataGridColumn.WidthProperty) { DataGridHelper.OnColumnWidthChanged(this, e); } else if (e.Property == DataGrid.CellStyleProperty || e.Property == DataGridColumn.CellStyleProperty || e.Property == StyleProperty) { DataGridHelper.TransferProperty(this, StyleProperty); } else if (e.Property == DataGrid.IsReadOnlyProperty || e.Property == DataGridColumn.IsReadOnlyProperty || e.Property == IsReadOnlyProperty) { DataGridHelper.TransferProperty(this, IsReadOnlyProperty); } else if (e.Property == DataGridColumn.DisplayIndexProperty) { TabIndex = column.DisplayIndex; } else if (e.Property == DataGrid.IsKeyboardFocusWithinProperty) { UpdateVisualState(); } } // All the notifications which needs forward to columns if (DataGridHelper.ShouldRefreshCellContent(target)) { if (column != null && NeedsVisualTree) { if (!string.IsNullOrEmpty(propertyName)) { column.RefreshCellContent(this, propertyName); } else if (e != null && e.Property != null) { column.RefreshCellContent(this, e.Property.Name); } } } } #endregion #region Style private static object OnCoerceStyle(DependencyObject d, object baseValue) { var cell = d as DataGridCell; return DataGridHelper.GetCoercedTransferPropertyValue( cell, baseValue, StyleProperty, cell.Column, DataGridColumn.CellStyleProperty, cell.DataGridOwner, DataGrid.CellStyleProperty); } #endregion #region Template internal override void ChangeVisualState(bool useTransitions) { if (DataGridOwner == null) { return; } // CommonStates if (IsMouseOver) { VisualStates.GoToState(this, useTransitions, VisualStates.StateMouseOver, VisualStates.StateNormal); } else { VisualStateManager.GoToState(this, VisualStates.StateNormal, useTransitions); } // SelectionStates if (IsSelected) { VisualStates.GoToState(this, useTransitions, VisualStates.StateSelected, VisualStates.StateUnselected); } else { VisualStates.GoToState(this, useTransitions, VisualStates.StateUnselected); } // FocusStates if (DataGridOwner.IsKeyboardFocusWithin) { VisualStates.GoToState(this, useTransitions, VisualStates.StateFocused, VisualStates.StateUnfocused); } else { VisualStateManager.GoToState(this, VisualStates.StateUnfocused, useTransitions); } // CurrentStates if (IsCurrent) { VisualStates.GoToState(this, useTransitions, VisualStates.StateCurrent, VisualStates.StateRegular); } else { VisualStateManager.GoToState(this, VisualStates.StateRegular, useTransitions); } // Interaction states if (IsEditing) { VisualStates.GoToState(this, useTransitions, VisualStates.StateEditing, VisualStates.StateDisplay); } else { VisualStateManager.GoToState(this, VisualStates.StateDisplay, useTransitions); } base.ChangeVisualState(useTransitions); } ////// Builds a column's visual tree if not using templates. /// internal void BuildVisualTree() { if (NeedsVisualTree) { var column = Column; if (column != null) { // Work around a problem with BindingGroup not removing BindingExpressions. var row = RowOwner; if (row != null) { var bindingGroup = row.BindingGroup; if (bindingGroup != null) { RemoveBindingExpressions(bindingGroup, Content as DependencyObject); } } // Ask the column to build a visual tree and // hook the visual tree up through the Content property. Content = column.BuildVisualTree(IsEditing, RowDataItem, this); } } } private void RemoveBindingExpressions(BindingGroup bindingGroup, DependencyObject element) { if (element == null) return; // no content, hence no bindings to remove var bindingExpressions = bindingGroup.BindingExpressions; for (int i = 0; i < bindingExpressions.Count; i++) { if (VisualTreeHelper.IsAncestorOf(element, bindingExpressions[i].TargetElement, typeof(DataGridCell))) { bindingExpressions.RemoveAt(i--); } } } #endregion #region Editing ////// Whether the cell is in editing mode. /// public bool IsEditing { get { return (bool)GetValue(IsEditingProperty); } set { SetValue(IsEditingProperty, value); } } ////// Represents the IsEditing property. /// public static readonly DependencyProperty IsEditingProperty = DependencyProperty.Register("IsEditing", typeof(bool), typeof(DataGridCell), new FrameworkPropertyMetadata(false, new PropertyChangedCallback(OnIsEditingChanged))); private static void OnIsEditingChanged(object sender, DependencyPropertyChangedEventArgs e) { ((DataGridCell)sender).OnIsEditingChanged((bool)e.NewValue); } ////// Called when the value of IsEditing changes. /// ////// Coerces the value of ContentTemplate. /// /// The new value of IsEditing. protected virtual void OnIsEditingChanged(bool isEditing) { if (IsKeyboardFocusWithin && !IsKeyboardFocused) { // Keep focus on the cell when flipping modes Focus(); } // If templates aren't being used, then a new visual tree needs to be built. BuildVisualTree(); UpdateVisualState(); } internal void NotifyCurrentCellContainerChanged() { UpdateVisualState(); } ////// Whether the cell is the current cell. /// private bool IsCurrent { get { var row = RowOwner; var column = Column; if (row != null && column != null) { var dataGrid = row.DataGridOwner; if (dataGrid != null) { return dataGrid.CurrentItem == row.Item && dataGrid.CurrentColumn == column; } } return false; } } ////// Whether the cell can be placed in edit mode. /// public bool IsReadOnly { get { return (bool)GetValue(IsReadOnlyProperty); } } private static readonly DependencyPropertyKey IsReadOnlyPropertyKey = DependencyProperty.RegisterReadOnly("IsReadOnly", typeof(bool), typeof(DataGridCell), new FrameworkPropertyMetadata(false, OnNotifyIsReadOnlyChanged, OnCoerceIsReadOnly)); ////// The DependencyProperty for IsReadOnly. /// public static readonly DependencyProperty IsReadOnlyProperty = IsReadOnlyPropertyKey.DependencyProperty; private static object OnCoerceIsReadOnly(DependencyObject d, object baseValue) { var cell = d as DataGridCell; var column = cell.Column; var dataGrid = cell.DataGridOwner; // We dont use the cell & 'baseValue' here because this property is read only on cell. // the column may coerce a default value to 'true', so we'll use it's effective value for IsReadOnly // as the baseValue. return DataGridHelper.GetCoercedTransferPropertyValue( column, column.IsReadOnly, DataGridColumn.IsReadOnlyProperty, dataGrid, DataGrid.IsReadOnlyProperty); } private static void OnAnyLostFocus(object sender, RoutedEventArgs e) { // Get the ancestor cell of old focused element. // Set DataGrid.FocusedCell to null, if the cell doesn't // have keyboard focus. DataGridCell cell = DataGridHelper.FindVisualParent(e.OriginalSource as UIElement); if (cell != null && cell == sender) { DataGrid owner = cell.DataGridOwner; if (owner != null && !cell.IsKeyboardFocusWithin && owner.FocusedCell == cell) { owner.FocusedCell = null; } } } private static void OnAnyGotFocus(object sender, RoutedEventArgs e) { DataGridCell cell = DataGridHelper.FindVisualParent (e.OriginalSource as UIElement); if (cell != null && cell == sender) { DataGrid owner = cell.DataGridOwner; if (owner != null) { owner.FocusedCell = cell; } } } internal void BeginEdit(RoutedEventArgs e) { Debug.Assert(!IsEditing, "Should not call BeginEdit when IsEditing is true."); IsEditing = true; DataGridColumn column = Column; if (column != null) { // Ask the column to store the original value column.BeginEdit(Content as FrameworkElement, e); } RaisePreparingCellForEdit(e); } internal void CancelEdit() { Debug.Assert(IsEditing, "Should not call CancelEdit when IsEditing is false."); DataGridColumn column = Column; if (column != null) { // Ask the column to restore the original value column.CancelEdit(Content as FrameworkElement); } IsEditing = false; } internal bool CommitEdit() { Debug.Assert(IsEditing, "Should not call CommitEdit when IsEditing is false."); bool validationPassed = true; DataGridColumn column = Column; if (column != null) { // Ask the column to access the binding and update the data source // If validation fails, then remain in editing mode validationPassed = column.CommitEdit(Content as FrameworkElement); } if (validationPassed) { IsEditing = false; } return validationPassed; } private void RaisePreparingCellForEdit(RoutedEventArgs editingEventArgs) { DataGrid dataGridOwner = DataGridOwner; if (dataGridOwner != null) { FrameworkElement currentEditingElement = EditingElement; DataGridPreparingCellForEditEventArgs preparingCellForEditEventArgs = new DataGridPreparingCellForEditEventArgs(Column, RowOwner, editingEventArgs, currentEditingElement); dataGridOwner.OnPreparingCellForEdit(preparingCellForEditEventArgs); } } internal FrameworkElement EditingElement { get { // The editing element was stored in the Content property. return Content as FrameworkElement; } } #endregion #region Selection /// /// Whether the cell is selected or not. /// public bool IsSelected { get { return (bool)GetValue(IsSelectedProperty); } set { SetValue(IsSelectedProperty, value); } } ////// Represents the IsSelected property. /// public static readonly DependencyProperty IsSelectedProperty = DependencyProperty.Register("IsSelected", typeof(bool), typeof(DataGridCell), new FrameworkPropertyMetadata(false, new PropertyChangedCallback(OnIsSelectedChanged))); private static void OnIsSelectedChanged(object sender, DependencyPropertyChangedEventArgs e) { DataGridCell cell = (DataGridCell)sender; bool isSelected = (bool)e.NewValue; // There is no reason to notify the DataGrid if IsSelected's value came // from the DataGrid. if (!cell._syncingIsSelected) { DataGrid dataGrid = cell.DataGridOwner; if (dataGrid != null) { // Notify the DataGrid that a cell's IsSelected property changed // in case it was done programmatically instead of by the // DataGrid itself. dataGrid.CellIsSelectedChanged(cell, isSelected); } } cell.RaiseSelectionChangedEvent(isSelected); cell.UpdateVisualState(); } ////// Used to synchronize IsSelected with the DataGrid. /// Prevents unncessary notification back to the DataGrid. /// internal void SyncIsSelected(bool isSelected) { bool originalValue = _syncingIsSelected; _syncingIsSelected = true; try { IsSelected = isSelected; } finally { _syncingIsSelected = originalValue; } } private void RaiseSelectionChangedEvent(bool isSelected) { if (isSelected) { OnSelected(new RoutedEventArgs(SelectedEvent, this)); } else { OnUnselected(new RoutedEventArgs(UnselectedEvent, this)); } } ////// Raised when the item's IsSelected property becomes true. /// public static readonly RoutedEvent SelectedEvent = EventManager.RegisterRoutedEvent("Selected", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(DataGridCell)); ////// Raised when the item's IsSelected property becomes true. /// public event RoutedEventHandler Selected { add { AddHandler(SelectedEvent, value); } remove { RemoveHandler(SelectedEvent, value); } } ////// Called when IsSelected becomes true. Raises the Selected event. /// /// Empty event arguments. protected virtual void OnSelected(RoutedEventArgs e) { RaiseEvent(e); } ////// Raised when the item's IsSelected property becomes false. /// public static readonly RoutedEvent UnselectedEvent = EventManager.RegisterRoutedEvent("Unselected", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(DataGridCell)); ////// Raised when the item's IsSelected property becomes false. /// public event RoutedEventHandler Unselected { add { AddHandler(UnselectedEvent, value); } remove { RemoveHandler(UnselectedEvent, value); } } ////// Called when IsSelected becomes false. Raises the Unselected event. /// /// Empty event arguments. protected virtual void OnUnselected(RoutedEventArgs e) { RaiseEvent(e); } #endregion #region GridLines // Different parts of the DataGrid draw different pieces of the GridLines. // Cells draw a single line on their right side. ////// Measure. This is overridden so that the cell can extend its size to account for a grid line on the right. /// protected override Size MeasureOverride(Size constraint) { // Make space for the GridLine on the right: // Remove space from the constraint (since it implicitly includes the GridLine's thickness), // call the base implementation, and add the thickness back for the returned size. if (DataGridHelper.IsGridLineVisible(DataGridOwner, /*isHorizontal = */ false)) { double thickness = DataGridOwner.VerticalGridLineThickness; Size desiredSize = base.MeasureOverride(DataGridHelper.SubtractFromSize(constraint, thickness, /*height = */ false)); desiredSize.Width += thickness; return desiredSize; } else { return base.MeasureOverride(constraint); } } ////// Arrange. This is overriden so that the cell can position its content to account for a grid line on the right. /// /// Arrange size protected override Size ArrangeOverride(Size arrangeSize) { // We don't need to adjust the Arrange position of the content. By default it is arranged at 0,0 and we're // adding a line to the right. All we have to do is compress and extend the size, just like Measure. if (DataGridHelper.IsGridLineVisible(DataGridOwner, /*isHorizontal = */ false)) { double thickness = DataGridOwner.VerticalGridLineThickness; Size returnSize = base.ArrangeOverride(DataGridHelper.SubtractFromSize(arrangeSize, thickness, /*height = */ false)); returnSize.Width += thickness; return returnSize; } else { return base.ArrangeOverride(arrangeSize); } } ////// OnRender. Overriden to draw a vertical line on the right. /// /// protected override void OnRender(DrawingContext drawingContext) { base.OnRender(drawingContext); if (DataGridHelper.IsGridLineVisible(DataGridOwner, /*isHorizontal = */ false)) { double thickness = DataGridOwner.VerticalGridLineThickness; Rect rect = new Rect(new Size(thickness, RenderSize.Height)); rect.X = RenderSize.Width - thickness; drawingContext.DrawRectangle(DataGridOwner.VerticalGridLinesBrush, null, rect); } } #endregion #region Input private static void OnAnyMouseLeftButtonDownThunk(object sender, MouseButtonEventArgs e) { ((DataGridCell)sender).OnAnyMouseLeftButtonDown(e); } ////// The left mouse button was pressed /// /// private void OnAnyMouseLeftButtonDown(MouseButtonEventArgs e) { bool focusWithin = IsKeyboardFocusWithin; bool isCtrlKeyPressed = (Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control; if (focusWithin && !isCtrlKeyPressed && !e.Handled && !IsEditing && !IsReadOnly && IsSelected) { // The cell is focused and there are no other special selection gestures, // enter edit mode. DataGrid dataGridOwner = DataGridOwner; if (dataGridOwner != null) { // The cell was clicked, which means that other cells may // need to be de-selected, let the DataGrid handle that. dataGridOwner.HandleSelectionForCellInput(this, /* startDragging = */ false, /* allowsExtendSelect = */ true, /* allowsMinimalSelect = */ false); // Enter edit mode dataGridOwner.BeginEdit(e); e.Handled = true; } } else if (!focusWithin || !IsSelected || isCtrlKeyPressed) { if (!focusWithin) { // The cell should receive focus on click Focus(); } DataGrid dataGridOwner = DataGridOwner; if (dataGridOwner != null) { // Let the DataGrid process selection dataGridOwner.HandleSelectionForCellInput(this, /* startDragging = */ Mouse.Captured == null, /* allowsExtendSelect = */ true, /* allowsMinimalSelect = */ true); } e.Handled = true; } #if PUBLIC_ONINPUT else { SendInputToColumn(e); } #endif } ////// Reporting text composition. /// protected override void OnTextInput(TextCompositionEventArgs e) { SendInputToColumn(e); } ////// Reporting a key was pressed. /// protected override void OnKeyDown(KeyEventArgs e) { SendInputToColumn(e); } #if PUBLIC_ONINPUT // ////// Reporting a key was released /// protected override void OnKeyUp(KeyEventArgs e) { SendInputToColumn(e); } ////// Reporting the mouse button was released /// protected override void OnMouseUp(MouseButtonEventArgs e) { SendInputToColumn(e); } #endif private void SendInputToColumn(InputEventArgs e) { var column = Column; if (column != null) { column.OnInput(e); } } #endregion #region Frozen Columns ////// Coercion call back for clip property which ensures that the cell overlapping with frozen /// column gets clipped appropriately. /// /// /// ///private static object OnCoerceClip(DependencyObject d, object baseValue) { DataGridCell cell = (DataGridCell)d; Geometry geometry = baseValue as Geometry; Geometry frozenGeometry = DataGridHelper.GetFrozenClipForCell(cell); if (frozenGeometry != null) { if (geometry == null) { return frozenGeometry; } geometry = new CombinedGeometry(GeometryCombineMode.Intersect, geometry, frozenGeometry); } return geometry; } #endregion #region Helpers internal DataGrid DataGridOwner { get { if (_owner != null) { DataGrid dataGridOwner = _owner.DataGridOwner; if (dataGridOwner == null) { dataGridOwner = ItemsControl.ItemsControlFromItemContainer(_owner) as DataGrid; } return dataGridOwner; } return null; } } private Panel ParentPanel { get { return VisualParent as Panel; } } internal DataGridRow RowOwner { get { return _owner; } } internal object RowDataItem { get { DataGridRow row = RowOwner; if (row != null) { return row.Item; } return DataContext; } } private DataGridCellsPresenter CellsPresenter { get { return ItemsControl.ItemsControlFromItemContainer(this) as DataGridCellsPresenter; } } private bool NeedsVisualTree { get { return (ContentTemplate == null) && (ContentTemplateSelector == null); } } #endregion #region Data private DataGridRow _owner; private ContainerTracking _tracker; private bool _syncingIsSelected; // Used to prevent unnecessary notifications #endregion } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- ExpressionWriter.cs
- PropertyTab.cs
- GenericNameHandler.cs
- TableSectionStyle.cs
- HttpApplicationStateBase.cs
- AuthenticatedStream.cs
- MethodBuilder.cs
- HttpRequestContext.cs
- FileDialogCustomPlace.cs
- WebPartManagerInternals.cs
- Point3D.cs
- WinOEToolBoxItem.cs
- CounterSample.cs
- DataGrid.cs
- CodeMemberProperty.cs
- Int16Storage.cs
- CollectionViewGroupInternal.cs
- ClassDataContract.cs
- BufferManager.cs
- TextBreakpoint.cs
- ResizeGrip.cs
- DrawingCollection.cs
- OraclePermissionAttribute.cs
- CultureSpecificStringDictionary.cs
- ConvertersCollection.cs
- ComplexBindingPropertiesAttribute.cs
- XmlnsPrefixAttribute.cs
- ViewLoader.cs
- Thread.cs
- SqlSupersetValidator.cs
- storepermission.cs
- BaseCollection.cs
- TextServicesLoader.cs
- ListItemConverter.cs
- TraceSection.cs
- NativeRightsManagementAPIsStructures.cs
- WhitespaceRuleLookup.cs
- BaseServiceProvider.cs
- ListViewItemEventArgs.cs
- AuthenticationException.cs
- EdmItemError.cs
- UnmanagedMarshal.cs
- SqlFileStream.cs
- ConfigXmlSignificantWhitespace.cs
- SqlUserDefinedAggregateAttribute.cs
- XmlSchemaObject.cs
- BulletedListDesigner.cs
- ValidationEventArgs.cs
- HostedHttpRequestAsyncResult.cs
- DesignerTextViewAdapter.cs
- SimpleLine.cs
- RoleServiceManager.cs
- DragCompletedEventArgs.cs
- ObsoleteAttribute.cs
- CssClassPropertyAttribute.cs
- LockCookie.cs
- XmlC14NWriter.cs
- ValueTypeFixupInfo.cs
- OptimizerPatterns.cs
- Floater.cs
- MiniMapControl.xaml.cs
- DataGridViewColumnEventArgs.cs
- NumberFunctions.cs
- BamlTreeUpdater.cs
- WebPartConnectionCollection.cs
- CompatibleIComparer.cs
- StrongName.cs
- MembershipUser.cs
- ResourcesBuildProvider.cs
- StyleTypedPropertyAttribute.cs
- MonthCalendar.cs
- PropertyReferenceSerializer.cs
- AutomationPeer.cs
- CompatibleIComparer.cs
- WindowsAltTab.cs
- CollectionViewSource.cs
- CodeSnippetCompileUnit.cs
- DataListItemEventArgs.cs
- MD5.cs
- LogEntryHeaderSerializer.cs
- TagPrefixAttribute.cs
- cookiecollection.cs
- SystemColors.cs
- OdbcEnvironment.cs
- ColumnMapVisitor.cs
- TdsEnums.cs
- SqlNode.cs
- KeyPullup.cs
- NetworkCredential.cs
- XmlObjectSerializer.cs
- UniqueIdentifierService.cs
- GenericParameterDataContract.cs
- Vector3DKeyFrameCollection.cs
- NameValueCollection.cs
- NativeActivity.cs
- Vector3DCollectionConverter.cs
- SimpleMailWebEventProvider.cs
- RuleSetBrowserDialog.cs
- Compilation.cs
- DataGridViewColumnConverter.cs