Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / System / Windows / Controls / Primitives / DataGridCellsPresenter.cs / 1305600 / DataGridCellsPresenter.cs
//---------------------------------------------------------------------------- // // Copyright (C) Microsoft Corporation. All rights reserved. // //--------------------------------------------------------------------------- using System; using System.Collections.ObjectModel; using System.Collections.Specialized; using System.ComponentModel; using System.Diagnostics; using System.Windows; using System.Windows.Controls; using System.Windows.Media; using MS.Internal; namespace System.Windows.Controls.Primitives { ////// A control that will be responsible for generating cells. /// This control is meant to be specified within the template of a DataGridRow. /// The APIs from ItemsControl do not match up nicely with the meaning of a /// row, which is why this is being factored out. /// /// The data item for the row is added n times to the Items collection, /// where n is the number of columns in the DataGrid. This is implemented /// using a special collection to avoid keeping multiple references to the /// same object. /// public class DataGridCellsPresenter : ItemsControl { #region Constructors ////// Instantiates global information. /// static DataGridCellsPresenter() { DefaultStyleKeyProperty.OverrideMetadata(typeof(DataGridCellsPresenter), new FrameworkPropertyMetadata(typeof(DataGridCellsPresenter))); ItemsPanelProperty.OverrideMetadata(typeof(DataGridCellsPresenter), new FrameworkPropertyMetadata(new ItemsPanelTemplate(new FrameworkElementFactory(typeof(DataGridCellsPanel))))); FocusableProperty.OverrideMetadata(typeof(DataGridCellsPresenter), new FrameworkPropertyMetadata(false)); HeightProperty.OverrideMetadata(typeof(DataGridCellsPresenter), new FrameworkPropertyMetadata(OnNotifyHeightPropertyChanged, OnCoerceHeight)); MinHeightProperty.OverrideMetadata(typeof(DataGridCellsPresenter), new FrameworkPropertyMetadata(OnNotifyHeightPropertyChanged, OnCoerceMinHeight)); VirtualizingStackPanel.IsVirtualizingProperty.OverrideMetadata( typeof(DataGridCellsPresenter), new FrameworkPropertyMetadata(false, new PropertyChangedCallback(OnIsVirtualizingPropertyChanged), new CoerceValueCallback(OnCoerceIsVirtualizingProperty))); VirtualizingStackPanel.VirtualizationModeProperty.OverrideMetadata(typeof(DataGridCellsPresenter), new FrameworkPropertyMetadata(VirtualizationMode.Recycling)); } ////// Instantiates a new instance of this class. /// public DataGridCellsPresenter() { } #endregion #region Row Communication ////// Tells the row owner about this element. /// public override void OnApplyTemplate() { #if BindingGroups if (ItemBindingGroup == null) { ItemBindingGroup = new BindingGroup(); } #endif base.OnApplyTemplate(); DataGridRow owningRow = DataGridRowOwner; if (owningRow != null) { owningRow.CellsPresenter = this; Item = owningRow.Item; } // At the time that a Row is prepared we can't [....] because the CellsPresenter isn't created yet. // Doing it here ensures that the CellsPresenter is in the visual tree. SyncProperties(false); } ////// Update all properties that get a value from the DataGrid /// ////// See comment on DataGridRow.SyncProperties /// internal void SyncProperties(bool forcePrepareCells) { var dataGridOwner = DataGridOwner; if (dataGridOwner == null) { return; } DataGridHelper.TransferProperty(this, HeightProperty); DataGridHelper.TransferProperty(this, MinHeightProperty); DataGridHelper.TransferProperty(this, VirtualizingStackPanel.IsVirtualizingProperty); // This is a convenient way to walk through all cells and force them to call CoerceValue(StyleProperty) NotifyPropertyChanged(this, new DependencyPropertyChangedEventArgs(DataGrid.CellStyleProperty, null, null), DataGridNotificationTarget.Cells); // We may have missed an Add / Remove of a column from the grid (DataGridRow.OnColumnsChanged) // [....] the MultipleCopiesCollection count and update the Column on changed cells MultipleCopiesCollection cellItems = ItemsSource as MultipleCopiesCollection; if (cellItems != null) { DataGridCell cell; ObservableCollectioncolumns = dataGridOwner.Columns; int newColumnCount = columns.Count; int oldColumnCount = cellItems.Count; int dirtyCount = 0; if (newColumnCount != oldColumnCount) { cellItems.SyncToCount(newColumnCount); // Newly added or removed containers will be updated by the generator via PrepareContainer. // All others may have a different column dirtyCount = Math.Min(newColumnCount, oldColumnCount); } else if (forcePrepareCells) { dirtyCount = newColumnCount; } DataGridRow row = DataGridRowOwner; bool arrangeInvalidated = false; // Prepare the cells until dirtyCount is reached. Also invalidate the cells panel's measure // and arrange if there is a mismatch between cell.ActualWidth and Column.Width.DisplayValue for (int i = 0; i < dirtyCount; i++) { cell = (DataGridCell)ItemContainerGenerator.ContainerFromIndex(i); if (cell != null) { cell.PrepareCell(row.Item, this, row); if (!arrangeInvalidated && !DoubleUtil.AreClose(cell.ActualWidth, columns[i].Width.DisplayValue)) { InvalidateDataGridCellsPanelMeasureAndArrange(); arrangeInvalidated = true; } } } // Keep searching for the mismatch between cell.ActualWidth // and Column.Width.DisplayValue if (!arrangeInvalidated) { for (int i = dirtyCount; i < newColumnCount; i++) { cell = (DataGridCell)ItemContainerGenerator.ContainerFromIndex(i); if (cell != null) { if (!DoubleUtil.AreClose(cell.ActualWidth, columns[i].Width.DisplayValue)) { InvalidateDataGridCellsPanelMeasureAndArrange(); break; } } } } } } private static object OnCoerceHeight(DependencyObject d, object baseValue) { var cellsPresenter = d as DataGridCellsPresenter; return DataGridHelper.GetCoercedTransferPropertyValue( cellsPresenter, baseValue, HeightProperty, cellsPresenter.DataGridOwner, DataGrid.RowHeightProperty); } private static object OnCoerceMinHeight(DependencyObject d, object baseValue) { var cellsPresenter = d as DataGridCellsPresenter; return DataGridHelper.GetCoercedTransferPropertyValue( cellsPresenter, baseValue, MinHeightProperty, cellsPresenter.DataGridOwner, DataGrid.MinRowHeightProperty); } #endregion #region Data Item /// /// The item that the row represents. This item is an entry in the list of items from the DataGrid. /// From this item, cells are generated for each column in the DataGrid. /// public object Item { get { return _item; } internal set { if (_item != value) { object oldItem = _item; _item = value; OnItemChanged(oldItem, _item); } } } ////// Called when the value of the Item property changes. /// /// The old value of Item. /// The new value of Item. protected virtual void OnItemChanged(object oldItem, object newItem) { ObservableCollectioncolumns = Columns; if (columns != null) { // Either update or create a collection that will return the row's data item // n number of times, where n is the number of columns. MultipleCopiesCollection cellItems = ItemsSource as MultipleCopiesCollection; if (cellItems == null) { cellItems = new MultipleCopiesCollection(newItem, columns.Count); ItemsSource = cellItems; } else { cellItems.CopiedItem = newItem; } } } #endregion #region Cell Container Generation /// /// Determines if an item is its own container. /// /// The item to test. ///true if the item is a DataGridCell, false otherwise. protected override bool IsItemItsOwnContainerOverride(object item) { return item is DataGridCell; } ////// Method which returns the result of IsItemItsOwnContainerOverride to be used internally /// internal bool IsItemItsOwnContainerInternal(object item) { return IsItemItsOwnContainerOverride(item); } ////// Instantiates an instance of a container. /// ///A new DataGridCell. protected override DependencyObject GetContainerForItemOverride() { return new DataGridCell(); } ////// Prepares a new container for a given item. /// /// The new container. /// The item that the container represents. protected override void PrepareContainerForItemOverride(DependencyObject element, object item) { DataGridCell cell = (DataGridCell)element; DataGridRow rowOwner = DataGridRowOwner; if (cell.RowOwner != rowOwner) { cell.Tracker.StartTracking(ref _cellTrackingRoot); } cell.PrepareCell(item, this, rowOwner); } ////// Clears a container of references. /// /// The container being cleared. /// The data item that the container represented. protected override void ClearContainerForItemOverride(DependencyObject element, object item) { DataGridCell cell = (DataGridCell)element; DataGridRow rowOwner = DataGridRowOwner; if (cell.RowOwner == rowOwner) { cell.Tracker.StopTracking(ref _cellTrackingRoot); } cell.ClearCell(rowOwner); } ////// Notification from the DataGrid that the columns collection has changed. /// /// The columns collection. /// The event arguments from the collection's change event. protected internal virtual void OnColumnsChanged(ObservableCollectioncolumns, NotifyCollectionChangedEventArgs e) { // Update the ItemsSource for the cells MultipleCopiesCollection cellItems = ItemsSource as MultipleCopiesCollection; if (cellItems != null) { cellItems.MirrorCollectionChange(e); } // For a reset event the only thing the MultipleCopiesCollection can do is set its count to 0. Debug.Assert( e.Action != NotifyCollectionChangedAction.Reset || columns.Count == 0, "A Reset event should only be fired for a Clear event from the columns collection"); } #endregion #region Notification Propagation /// /// Notification of Height & MinHeight changes. /// private static void OnNotifyHeightPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ((DataGridCellsPresenter)d).NotifyPropertyChanged(d, e, DataGridNotificationTarget.CellsPresenter); } ////// General notification for DependencyProperty changes from the grid or from columns. /// internal void NotifyPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e, DataGridNotificationTarget target) { NotifyPropertyChanged(d, string.Empty, e, target); } ////// General notification for DependencyProperty changes from the grid or from columns. /// internal void NotifyPropertyChanged(DependencyObject d, string propertyName, DependencyPropertyChangedEventArgs e, DataGridNotificationTarget target) { if (DataGridHelper.ShouldNotifyCellsPresenter(target)) { if (e.Property == DataGridColumn.WidthProperty || e.Property == DataGridColumn.DisplayIndexProperty) { if (((DataGridColumn)d).IsVisible) { InvalidateDataGridCellsPanelMeasureAndArrange(); } } else if (e.Property == DataGrid.FrozenColumnCountProperty || e.Property == DataGridColumn.VisibilityProperty || e.Property == DataGrid.CellsPanelHorizontalOffsetProperty || e.Property == DataGrid.HorizontalScrollOffsetProperty || string.Compare(propertyName, "ViewportWidth", StringComparison.Ordinal) == 0 || string.Compare(propertyName, "DelayedColumnWidthComputation", StringComparison.Ordinal) == 0) { InvalidateDataGridCellsPanelMeasureAndArrange(); } else if (string.Compare(propertyName, "RealizedColumnsBlockListForNonVirtualizedRows", StringComparison.Ordinal) == 0) { InvalidateDataGridCellsPanelMeasureAndArrange(/* withColumnVirtualization */ false); } else if (string.Compare(propertyName, "RealizedColumnsBlockListForVirtualizedRows", StringComparison.Ordinal) == 0) { InvalidateDataGridCellsPanelMeasureAndArrange(/* withColumnVirtualization */ true); } else if (e.Property == DataGrid.RowHeightProperty || e.Property == HeightProperty) { DataGridHelper.TransferProperty(this, HeightProperty); } else if (e.Property == DataGrid.MinRowHeightProperty || e.Property == MinHeightProperty) { DataGridHelper.TransferProperty(this, MinHeightProperty); } else if (e.Property == DataGrid.EnableColumnVirtualizationProperty) { DataGridHelper.TransferProperty(this, VirtualizingStackPanel.IsVirtualizingProperty); } } if (DataGridHelper.ShouldNotifyCells(target) || DataGridHelper.ShouldRefreshCellContent(target)) { ContainerTrackingtracker = _cellTrackingRoot; while (tracker != null) { tracker.Container.NotifyPropertyChanged(d, propertyName, e, target); tracker = tracker.Next; } } } #endregion #region GridLines // Different parts of the DataGrid draw different pieces of the GridLines. // Rows draw a single horizontal line on the bottom. The DataGridDetailsPresenter is the element that handles it. /// /// Measure. This is overridden so that the row can extend its size to account for a grid line on the bottom. /// /// ///protected override Size MeasureOverride(Size availableSize) { // Make space for the GridLine on the bottom. // 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. var row = DataGridRowOwner; if (row == null) { return base.MeasureOverride(availableSize); } var dataGrid = row.DataGridOwner; if (dataGrid == null) { return base.MeasureOverride(availableSize); } if (DataGridHelper.IsGridLineVisible(dataGrid, /*isHorizontal = */ true)) { double thickness = dataGrid.HorizontalGridLineThickness; Size desiredSize = base.MeasureOverride(DataGridHelper.SubtractFromSize(availableSize, thickness, /*height = */ true)); desiredSize.Height += thickness; return desiredSize; } else { return base.MeasureOverride(availableSize); } } /// /// Arrange. This is overriden so that the row can position its content to account for a grid line on the bottom. /// /// Arrange size protected override Size ArrangeOverride(Size finalSize) { // 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 bottom. All we have to do is compress and extend the size, just like Measure. var row = DataGridRowOwner; if (row == null) { return base.ArrangeOverride(finalSize); } var dataGrid = row.DataGridOwner; if (dataGrid == null) { return base.ArrangeOverride(finalSize); } if (DataGridHelper.IsGridLineVisible(dataGrid, /*isHorizontal = */ true)) { double thickness = dataGrid.HorizontalGridLineThickness; Size returnSize = base.ArrangeOverride(DataGridHelper.SubtractFromSize(finalSize, thickness, /*height = */ true)); returnSize.Height += thickness; return returnSize; } else { return base.ArrangeOverride(finalSize); } } ////// OnRender. Overriden to draw a horizontal line underneath the content. /// /// protected override void OnRender(DrawingContext drawingContext) { base.OnRender(drawingContext); var row = DataGridRowOwner; if (row == null) { return; } var dataGrid = row.DataGridOwner; if (dataGrid == null) { return; } if (DataGridHelper.IsGridLineVisible(dataGrid, /*isHorizontal = */ true)) { double thickness = dataGrid.HorizontalGridLineThickness; Rect rect = new Rect(new Size(RenderSize.Width, thickness)); rect.Y = RenderSize.Height - thickness; drawingContext.DrawRectangle(dataGrid.HorizontalGridLinesBrush, null, rect); } } #endregion #region Column Virtualization ////// Property changed callback for VirtualizingStackPanel.IsVirtualizing property /// private static void OnIsVirtualizingPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { DataGridCellsPresenter cellsPresenter = (DataGridCellsPresenter)d; DataGridHelper.TransferProperty(cellsPresenter, VirtualizingStackPanel.IsVirtualizingProperty); if (e.OldValue != cellsPresenter.GetValue(VirtualizingStackPanel.IsVirtualizingProperty)) { cellsPresenter.InvalidateDataGridCellsPanelMeasureAndArrange(); } } ////// Coercion callback for VirtualizingStackPanel.IsVirtualizing property /// private static object OnCoerceIsVirtualizingProperty(DependencyObject d, object baseValue) { var cellsPresenter = d as DataGridCellsPresenter; return DataGridHelper.GetCoercedTransferPropertyValue( cellsPresenter, baseValue, VirtualizingStackPanel.IsVirtualizingProperty, cellsPresenter.DataGridOwner, DataGrid.EnableColumnVirtualizationProperty); } ////// Helper method which invalidate the underlying itemshost's measure and arrange /// internal void InvalidateDataGridCellsPanelMeasureAndArrange() { if (_internalItemsHost != null) { _internalItemsHost.InvalidateMeasure(); _internalItemsHost.InvalidateArrange(); } } ////// Helper method which invalidate the underlying itemshost's measure and arrange /// /// /// True to invalidate only when virtualization is on. /// False to invalidate only when virtualization is off. /// private void InvalidateDataGridCellsPanelMeasureAndArrange(bool withColumnVirtualization) { // Invalidates measure and arrange if the flag and the virtualization // are either both true or both false. if (withColumnVirtualization == VirtualizingStackPanel.GetIsVirtualizing(this)) { InvalidateDataGridCellsPanelMeasureAndArrange(); } } ////// Workaround for not being able to access the panel instance of /// itemscontrol directly /// internal Panel InternalItemsHost { get { return _internalItemsHost; } set { _internalItemsHost = value; } } ////// Method which tries to scroll a cell for given index into the scroll view /// /// internal void ScrollCellIntoView(int index) { DataGridCellsPanel itemsHost = InternalItemsHost as DataGridCellsPanel; if (itemsHost != null) { itemsHost.InternalBringIndexIntoView(index); return; } } #endregion #region Helpers ////// The DataGrid that owns this control /// private DataGrid DataGridOwner { get { DataGridRow parent = DataGridRowOwner; if (parent != null) { return parent.DataGridOwner; } return null; } } ////// The DataGridRow that owns this control. /// internal DataGridRow DataGridRowOwner { get { return DataGridHelper.FindParent(this); } } private ObservableCollection Columns { get { DataGridRow owningRow = DataGridRowOwner; DataGrid owningDataGrid = (owningRow != null) ? owningRow.DataGridOwner : null; return (owningDataGrid != null) ? owningDataGrid.Columns : null; } } internal ContainerTracking CellTrackingRoot { get { return _cellTrackingRoot; } } #endregion #region Data private object _item; private ContainerTracking _cellTrackingRoot; // Root of a linked list of active cell containers private Panel _internalItemsHost; #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.Collections.Specialized; using System.ComponentModel; using System.Diagnostics; using System.Windows; using System.Windows.Controls; using System.Windows.Media; using MS.Internal; namespace System.Windows.Controls.Primitives { /// /// A control that will be responsible for generating cells. /// This control is meant to be specified within the template of a DataGridRow. /// The APIs from ItemsControl do not match up nicely with the meaning of a /// row, which is why this is being factored out. /// /// The data item for the row is added n times to the Items collection, /// where n is the number of columns in the DataGrid. This is implemented /// using a special collection to avoid keeping multiple references to the /// same object. /// public class DataGridCellsPresenter : ItemsControl { #region Constructors ////// Instantiates global information. /// static DataGridCellsPresenter() { DefaultStyleKeyProperty.OverrideMetadata(typeof(DataGridCellsPresenter), new FrameworkPropertyMetadata(typeof(DataGridCellsPresenter))); ItemsPanelProperty.OverrideMetadata(typeof(DataGridCellsPresenter), new FrameworkPropertyMetadata(new ItemsPanelTemplate(new FrameworkElementFactory(typeof(DataGridCellsPanel))))); FocusableProperty.OverrideMetadata(typeof(DataGridCellsPresenter), new FrameworkPropertyMetadata(false)); HeightProperty.OverrideMetadata(typeof(DataGridCellsPresenter), new FrameworkPropertyMetadata(OnNotifyHeightPropertyChanged, OnCoerceHeight)); MinHeightProperty.OverrideMetadata(typeof(DataGridCellsPresenter), new FrameworkPropertyMetadata(OnNotifyHeightPropertyChanged, OnCoerceMinHeight)); VirtualizingStackPanel.IsVirtualizingProperty.OverrideMetadata( typeof(DataGridCellsPresenter), new FrameworkPropertyMetadata(false, new PropertyChangedCallback(OnIsVirtualizingPropertyChanged), new CoerceValueCallback(OnCoerceIsVirtualizingProperty))); VirtualizingStackPanel.VirtualizationModeProperty.OverrideMetadata(typeof(DataGridCellsPresenter), new FrameworkPropertyMetadata(VirtualizationMode.Recycling)); } ////// Instantiates a new instance of this class. /// public DataGridCellsPresenter() { } #endregion #region Row Communication ////// Tells the row owner about this element. /// public override void OnApplyTemplate() { #if BindingGroups if (ItemBindingGroup == null) { ItemBindingGroup = new BindingGroup(); } #endif base.OnApplyTemplate(); DataGridRow owningRow = DataGridRowOwner; if (owningRow != null) { owningRow.CellsPresenter = this; Item = owningRow.Item; } // At the time that a Row is prepared we can't [....] because the CellsPresenter isn't created yet. // Doing it here ensures that the CellsPresenter is in the visual tree. SyncProperties(false); } ////// Update all properties that get a value from the DataGrid /// ////// See comment on DataGridRow.SyncProperties /// internal void SyncProperties(bool forcePrepareCells) { var dataGridOwner = DataGridOwner; if (dataGridOwner == null) { return; } DataGridHelper.TransferProperty(this, HeightProperty); DataGridHelper.TransferProperty(this, MinHeightProperty); DataGridHelper.TransferProperty(this, VirtualizingStackPanel.IsVirtualizingProperty); // This is a convenient way to walk through all cells and force them to call CoerceValue(StyleProperty) NotifyPropertyChanged(this, new DependencyPropertyChangedEventArgs(DataGrid.CellStyleProperty, null, null), DataGridNotificationTarget.Cells); // We may have missed an Add / Remove of a column from the grid (DataGridRow.OnColumnsChanged) // [....] the MultipleCopiesCollection count and update the Column on changed cells MultipleCopiesCollection cellItems = ItemsSource as MultipleCopiesCollection; if (cellItems != null) { DataGridCell cell; ObservableCollectioncolumns = dataGridOwner.Columns; int newColumnCount = columns.Count; int oldColumnCount = cellItems.Count; int dirtyCount = 0; if (newColumnCount != oldColumnCount) { cellItems.SyncToCount(newColumnCount); // Newly added or removed containers will be updated by the generator via PrepareContainer. // All others may have a different column dirtyCount = Math.Min(newColumnCount, oldColumnCount); } else if (forcePrepareCells) { dirtyCount = newColumnCount; } DataGridRow row = DataGridRowOwner; bool arrangeInvalidated = false; // Prepare the cells until dirtyCount is reached. Also invalidate the cells panel's measure // and arrange if there is a mismatch between cell.ActualWidth and Column.Width.DisplayValue for (int i = 0; i < dirtyCount; i++) { cell = (DataGridCell)ItemContainerGenerator.ContainerFromIndex(i); if (cell != null) { cell.PrepareCell(row.Item, this, row); if (!arrangeInvalidated && !DoubleUtil.AreClose(cell.ActualWidth, columns[i].Width.DisplayValue)) { InvalidateDataGridCellsPanelMeasureAndArrange(); arrangeInvalidated = true; } } } // Keep searching for the mismatch between cell.ActualWidth // and Column.Width.DisplayValue if (!arrangeInvalidated) { for (int i = dirtyCount; i < newColumnCount; i++) { cell = (DataGridCell)ItemContainerGenerator.ContainerFromIndex(i); if (cell != null) { if (!DoubleUtil.AreClose(cell.ActualWidth, columns[i].Width.DisplayValue)) { InvalidateDataGridCellsPanelMeasureAndArrange(); break; } } } } } } private static object OnCoerceHeight(DependencyObject d, object baseValue) { var cellsPresenter = d as DataGridCellsPresenter; return DataGridHelper.GetCoercedTransferPropertyValue( cellsPresenter, baseValue, HeightProperty, cellsPresenter.DataGridOwner, DataGrid.RowHeightProperty); } private static object OnCoerceMinHeight(DependencyObject d, object baseValue) { var cellsPresenter = d as DataGridCellsPresenter; return DataGridHelper.GetCoercedTransferPropertyValue( cellsPresenter, baseValue, MinHeightProperty, cellsPresenter.DataGridOwner, DataGrid.MinRowHeightProperty); } #endregion #region Data Item /// /// The item that the row represents. This item is an entry in the list of items from the DataGrid. /// From this item, cells are generated for each column in the DataGrid. /// public object Item { get { return _item; } internal set { if (_item != value) { object oldItem = _item; _item = value; OnItemChanged(oldItem, _item); } } } ////// Called when the value of the Item property changes. /// /// The old value of Item. /// The new value of Item. protected virtual void OnItemChanged(object oldItem, object newItem) { ObservableCollectioncolumns = Columns; if (columns != null) { // Either update or create a collection that will return the row's data item // n number of times, where n is the number of columns. MultipleCopiesCollection cellItems = ItemsSource as MultipleCopiesCollection; if (cellItems == null) { cellItems = new MultipleCopiesCollection(newItem, columns.Count); ItemsSource = cellItems; } else { cellItems.CopiedItem = newItem; } } } #endregion #region Cell Container Generation /// /// Determines if an item is its own container. /// /// The item to test. ///true if the item is a DataGridCell, false otherwise. protected override bool IsItemItsOwnContainerOverride(object item) { return item is DataGridCell; } ////// Method which returns the result of IsItemItsOwnContainerOverride to be used internally /// internal bool IsItemItsOwnContainerInternal(object item) { return IsItemItsOwnContainerOverride(item); } ////// Instantiates an instance of a container. /// ///A new DataGridCell. protected override DependencyObject GetContainerForItemOverride() { return new DataGridCell(); } ////// Prepares a new container for a given item. /// /// The new container. /// The item that the container represents. protected override void PrepareContainerForItemOverride(DependencyObject element, object item) { DataGridCell cell = (DataGridCell)element; DataGridRow rowOwner = DataGridRowOwner; if (cell.RowOwner != rowOwner) { cell.Tracker.StartTracking(ref _cellTrackingRoot); } cell.PrepareCell(item, this, rowOwner); } ////// Clears a container of references. /// /// The container being cleared. /// The data item that the container represented. protected override void ClearContainerForItemOverride(DependencyObject element, object item) { DataGridCell cell = (DataGridCell)element; DataGridRow rowOwner = DataGridRowOwner; if (cell.RowOwner == rowOwner) { cell.Tracker.StopTracking(ref _cellTrackingRoot); } cell.ClearCell(rowOwner); } ////// Notification from the DataGrid that the columns collection has changed. /// /// The columns collection. /// The event arguments from the collection's change event. protected internal virtual void OnColumnsChanged(ObservableCollectioncolumns, NotifyCollectionChangedEventArgs e) { // Update the ItemsSource for the cells MultipleCopiesCollection cellItems = ItemsSource as MultipleCopiesCollection; if (cellItems != null) { cellItems.MirrorCollectionChange(e); } // For a reset event the only thing the MultipleCopiesCollection can do is set its count to 0. Debug.Assert( e.Action != NotifyCollectionChangedAction.Reset || columns.Count == 0, "A Reset event should only be fired for a Clear event from the columns collection"); } #endregion #region Notification Propagation /// /// Notification of Height & MinHeight changes. /// private static void OnNotifyHeightPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ((DataGridCellsPresenter)d).NotifyPropertyChanged(d, e, DataGridNotificationTarget.CellsPresenter); } ////// General notification for DependencyProperty changes from the grid or from columns. /// internal void NotifyPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e, DataGridNotificationTarget target) { NotifyPropertyChanged(d, string.Empty, e, target); } ////// General notification for DependencyProperty changes from the grid or from columns. /// internal void NotifyPropertyChanged(DependencyObject d, string propertyName, DependencyPropertyChangedEventArgs e, DataGridNotificationTarget target) { if (DataGridHelper.ShouldNotifyCellsPresenter(target)) { if (e.Property == DataGridColumn.WidthProperty || e.Property == DataGridColumn.DisplayIndexProperty) { if (((DataGridColumn)d).IsVisible) { InvalidateDataGridCellsPanelMeasureAndArrange(); } } else if (e.Property == DataGrid.FrozenColumnCountProperty || e.Property == DataGridColumn.VisibilityProperty || e.Property == DataGrid.CellsPanelHorizontalOffsetProperty || e.Property == DataGrid.HorizontalScrollOffsetProperty || string.Compare(propertyName, "ViewportWidth", StringComparison.Ordinal) == 0 || string.Compare(propertyName, "DelayedColumnWidthComputation", StringComparison.Ordinal) == 0) { InvalidateDataGridCellsPanelMeasureAndArrange(); } else if (string.Compare(propertyName, "RealizedColumnsBlockListForNonVirtualizedRows", StringComparison.Ordinal) == 0) { InvalidateDataGridCellsPanelMeasureAndArrange(/* withColumnVirtualization */ false); } else if (string.Compare(propertyName, "RealizedColumnsBlockListForVirtualizedRows", StringComparison.Ordinal) == 0) { InvalidateDataGridCellsPanelMeasureAndArrange(/* withColumnVirtualization */ true); } else if (e.Property == DataGrid.RowHeightProperty || e.Property == HeightProperty) { DataGridHelper.TransferProperty(this, HeightProperty); } else if (e.Property == DataGrid.MinRowHeightProperty || e.Property == MinHeightProperty) { DataGridHelper.TransferProperty(this, MinHeightProperty); } else if (e.Property == DataGrid.EnableColumnVirtualizationProperty) { DataGridHelper.TransferProperty(this, VirtualizingStackPanel.IsVirtualizingProperty); } } if (DataGridHelper.ShouldNotifyCells(target) || DataGridHelper.ShouldRefreshCellContent(target)) { ContainerTrackingtracker = _cellTrackingRoot; while (tracker != null) { tracker.Container.NotifyPropertyChanged(d, propertyName, e, target); tracker = tracker.Next; } } } #endregion #region GridLines // Different parts of the DataGrid draw different pieces of the GridLines. // Rows draw a single horizontal line on the bottom. The DataGridDetailsPresenter is the element that handles it. /// /// Measure. This is overridden so that the row can extend its size to account for a grid line on the bottom. /// /// ///protected override Size MeasureOverride(Size availableSize) { // Make space for the GridLine on the bottom. // 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. var row = DataGridRowOwner; if (row == null) { return base.MeasureOverride(availableSize); } var dataGrid = row.DataGridOwner; if (dataGrid == null) { return base.MeasureOverride(availableSize); } if (DataGridHelper.IsGridLineVisible(dataGrid, /*isHorizontal = */ true)) { double thickness = dataGrid.HorizontalGridLineThickness; Size desiredSize = base.MeasureOverride(DataGridHelper.SubtractFromSize(availableSize, thickness, /*height = */ true)); desiredSize.Height += thickness; return desiredSize; } else { return base.MeasureOverride(availableSize); } } /// /// Arrange. This is overriden so that the row can position its content to account for a grid line on the bottom. /// /// Arrange size protected override Size ArrangeOverride(Size finalSize) { // 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 bottom. All we have to do is compress and extend the size, just like Measure. var row = DataGridRowOwner; if (row == null) { return base.ArrangeOverride(finalSize); } var dataGrid = row.DataGridOwner; if (dataGrid == null) { return base.ArrangeOverride(finalSize); } if (DataGridHelper.IsGridLineVisible(dataGrid, /*isHorizontal = */ true)) { double thickness = dataGrid.HorizontalGridLineThickness; Size returnSize = base.ArrangeOverride(DataGridHelper.SubtractFromSize(finalSize, thickness, /*height = */ true)); returnSize.Height += thickness; return returnSize; } else { return base.ArrangeOverride(finalSize); } } ////// OnRender. Overriden to draw a horizontal line underneath the content. /// /// protected override void OnRender(DrawingContext drawingContext) { base.OnRender(drawingContext); var row = DataGridRowOwner; if (row == null) { return; } var dataGrid = row.DataGridOwner; if (dataGrid == null) { return; } if (DataGridHelper.IsGridLineVisible(dataGrid, /*isHorizontal = */ true)) { double thickness = dataGrid.HorizontalGridLineThickness; Rect rect = new Rect(new Size(RenderSize.Width, thickness)); rect.Y = RenderSize.Height - thickness; drawingContext.DrawRectangle(dataGrid.HorizontalGridLinesBrush, null, rect); } } #endregion #region Column Virtualization ////// Property changed callback for VirtualizingStackPanel.IsVirtualizing property /// private static void OnIsVirtualizingPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { DataGridCellsPresenter cellsPresenter = (DataGridCellsPresenter)d; DataGridHelper.TransferProperty(cellsPresenter, VirtualizingStackPanel.IsVirtualizingProperty); if (e.OldValue != cellsPresenter.GetValue(VirtualizingStackPanel.IsVirtualizingProperty)) { cellsPresenter.InvalidateDataGridCellsPanelMeasureAndArrange(); } } ////// Coercion callback for VirtualizingStackPanel.IsVirtualizing property /// private static object OnCoerceIsVirtualizingProperty(DependencyObject d, object baseValue) { var cellsPresenter = d as DataGridCellsPresenter; return DataGridHelper.GetCoercedTransferPropertyValue( cellsPresenter, baseValue, VirtualizingStackPanel.IsVirtualizingProperty, cellsPresenter.DataGridOwner, DataGrid.EnableColumnVirtualizationProperty); } ////// Helper method which invalidate the underlying itemshost's measure and arrange /// internal void InvalidateDataGridCellsPanelMeasureAndArrange() { if (_internalItemsHost != null) { _internalItemsHost.InvalidateMeasure(); _internalItemsHost.InvalidateArrange(); } } ////// Helper method which invalidate the underlying itemshost's measure and arrange /// /// /// True to invalidate only when virtualization is on. /// False to invalidate only when virtualization is off. /// private void InvalidateDataGridCellsPanelMeasureAndArrange(bool withColumnVirtualization) { // Invalidates measure and arrange if the flag and the virtualization // are either both true or both false. if (withColumnVirtualization == VirtualizingStackPanel.GetIsVirtualizing(this)) { InvalidateDataGridCellsPanelMeasureAndArrange(); } } ////// Workaround for not being able to access the panel instance of /// itemscontrol directly /// internal Panel InternalItemsHost { get { return _internalItemsHost; } set { _internalItemsHost = value; } } ////// Method which tries to scroll a cell for given index into the scroll view /// /// internal void ScrollCellIntoView(int index) { DataGridCellsPanel itemsHost = InternalItemsHost as DataGridCellsPanel; if (itemsHost != null) { itemsHost.InternalBringIndexIntoView(index); return; } } #endregion #region Helpers ////// The DataGrid that owns this control /// private DataGrid DataGridOwner { get { DataGridRow parent = DataGridRowOwner; if (parent != null) { return parent.DataGridOwner; } return null; } } ////// The DataGridRow that owns this control. /// internal DataGridRow DataGridRowOwner { get { return DataGridHelper.FindParent(this); } } private ObservableCollection Columns { get { DataGridRow owningRow = DataGridRowOwner; DataGrid owningDataGrid = (owningRow != null) ? owningRow.DataGridOwner : null; return (owningDataGrid != null) ? owningDataGrid.Columns : null; } } internal ContainerTracking CellTrackingRoot { get { return _cellTrackingRoot; } } #endregion #region Data private object _item; private ContainerTracking _cellTrackingRoot; // Root of a linked list of active cell containers private Panel _internalItemsHost; #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
- CounterSample.cs
- PanelDesigner.cs
- BeginStoryboard.cs
- QilStrConcat.cs
- Polyline.cs
- StringFormat.cs
- StorageModelBuildProvider.cs
- EventItfInfo.cs
- PropertyFilterAttribute.cs
- ConfigXmlText.cs
- ParsedAttributeCollection.cs
- RequestCache.cs
- HorizontalAlignConverter.cs
- MasterPage.cs
- DataGridViewCellCancelEventArgs.cs
- Preprocessor.cs
- BoundsDrawingContextWalker.cs
- GenericEnumerator.cs
- TransactionContextManager.cs
- Verify.cs
- ResXFileRef.cs
- SqlFacetAttribute.cs
- Expression.cs
- Tokenizer.cs
- PageCatalogPart.cs
- UrlMappingsSection.cs
- EmptyCollection.cs
- WebPartRestoreVerb.cs
- wgx_commands.cs
- EpmCustomContentWriterNodeData.cs
- NamespaceList.cs
- HighContrastHelper.cs
- AbandonedMutexException.cs
- XmlQuerySequence.cs
- VBIdentifierTrimConverter.cs
- WebBrowserProgressChangedEventHandler.cs
- Formatter.cs
- SecurityKeyEntropyMode.cs
- TableLayoutStyleCollection.cs
- CodeTryCatchFinallyStatement.cs
- MdiWindowListStrip.cs
- ImpersonationContext.cs
- RTLAwareMessageBox.cs
- HTMLTagNameToTypeMapper.cs
- UnionExpr.cs
- TabItemAutomationPeer.cs
- UrlMapping.cs
- SQLMembershipProvider.cs
- DataSourceCacheDurationConverter.cs
- SystemInformation.cs
- EncodingInfo.cs
- DataGridViewColumnDesignTimeVisibleAttribute.cs
- VirtualPathUtility.cs
- PeerTransportElement.cs
- SqlFacetAttribute.cs
- SystemIcmpV4Statistics.cs
- WCFModelStrings.Designer.cs
- GlyphShapingProperties.cs
- WebBaseEventKeyComparer.cs
- XamlSerializationHelper.cs
- XmlReflectionImporter.cs
- StrokeIntersection.cs
- LayoutTableCell.cs
- PageThemeCodeDomTreeGenerator.cs
- BridgeDataReader.cs
- GuidTagList.cs
- CacheForPrimitiveTypes.cs
- VectorAnimationUsingKeyFrames.cs
- DataViewSetting.cs
- RuleRefElement.cs
- HiddenField.cs
- TrustLevel.cs
- ProcessHostServerConfig.cs
- ScrollItemPatternIdentifiers.cs
- XmlValidatingReaderImpl.cs
- XmlSchemaExternal.cs
- CodeChecksumPragma.cs
- DaylightTime.cs
- FileLogRecord.cs
- SemanticAnalyzer.cs
- OdbcConnectionPoolProviderInfo.cs
- IDataContractSurrogate.cs
- SymDocumentType.cs
- ReadWriteObjectLock.cs
- DesignerAttributeInfo.cs
- diagnosticsswitches.cs
- CapabilitiesState.cs
- TextRange.cs
- ExtensionCollection.cs
- ApplyTemplatesAction.cs
- UIElementIsland.cs
- X509SecurityTokenProvider.cs
- ConstrainedDataObject.cs
- CodeTypeParameterCollection.cs
- _TLSstream.cs
- XamlPoint3DCollectionSerializer.cs
- AcceptorSessionSymmetricMessageSecurityProtocol.cs
- X509CertificateInitiatorServiceCredential.cs
- ConcurrentQueue.cs
- ResourceCategoryAttribute.cs