Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / System / Windows / Controls / Primitives / DataGridDetailsPresenter.cs / 1305600 / DataGridDetailsPresenter.cs
//---------------------------------------------------------------------------- // // Copyright (C) Microsoft Corporation. All rights reserved. // //--------------------------------------------------------------------------- using System; using System.Diagnostics; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; namespace System.Windows.Controls.Primitives { public class DataGridDetailsPresenter : ContentPresenter { static DataGridDetailsPresenter() { DefaultStyleKeyProperty.OverrideMetadata(typeof(DataGridDetailsPresenter), new FrameworkPropertyMetadata(typeof(DataGridDetailsPresenter))); ContentTemplateProperty.OverrideMetadata(typeof(DataGridDetailsPresenter), new FrameworkPropertyMetadata(OnNotifyPropertyChanged, OnCoerceContentTemplate)); ContentTemplateSelectorProperty.OverrideMetadata(typeof(DataGridDetailsPresenter), new FrameworkPropertyMetadata(OnNotifyPropertyChanged, OnCoerceContentTemplateSelector)); EventManager.RegisterClassHandler(typeof(DataGridDetailsPresenter), MouseLeftButtonDownEvent, new MouseButtonEventHandler(OnAnyMouseLeftButtonDownThunk), true); } ////// Instantiates a new instance of this class. /// public DataGridDetailsPresenter() { } #region Automation protected override System.Windows.Automation.Peers.AutomationPeer OnCreateAutomationPeer() { return new System.Windows.Automation.Peers.DataGridDetailsPresenterAutomationPeer(this); } #endregion #region Coercion ////// Coerces the ContentTemplate property. /// private static object OnCoerceContentTemplate(DependencyObject d, object baseValue) { var details = d as DataGridDetailsPresenter; var row = details.DataGridRowOwner; var dataGrid = row != null ? row.DataGridOwner : null; return DataGridHelper.GetCoercedTransferPropertyValue( details, baseValue, ContentTemplateProperty, row, DataGridRow.DetailsTemplateProperty, dataGrid, DataGrid.RowDetailsTemplateProperty); } ////// Coerces the ContentTemplateSelector property. /// private static object OnCoerceContentTemplateSelector(DependencyObject d, object baseValue) { var details = d as DataGridDetailsPresenter; var row = details.DataGridRowOwner; var dataGrid = row != null ? row.DataGridOwner : null; return DataGridHelper.GetCoercedTransferPropertyValue( details, baseValue, ContentTemplateSelectorProperty, row, DataGridRow.DetailsTemplateSelectorProperty, dataGrid, DataGrid.RowDetailsTemplateSelectorProperty); } #endregion #region Row Communication protected internal override void OnVisualParentChanged(DependencyObject oldParent) { base.OnVisualParentChanged(oldParent); // DataGridRow.DetailsPresenter is used by automation peers // Give the Row a pointer to the RowHeader so that it can propagate down change notifications DataGridRow owner = DataGridRowOwner; if (owner != null) { owner.DetailsPresenter = this; // At the time that a Row is prepared we can't [....] because the DetailsPresenter isn't created yet. // Doing it here ensures that the DetailsPresenter is in the visual tree. SyncProperties(); } } private static void OnAnyMouseLeftButtonDownThunk(object sender, MouseButtonEventArgs e) { ((DataGridDetailsPresenter)sender).OnAnyMouseLeftButtonDown(e); } private void OnAnyMouseLeftButtonDown(System.Windows.Input.MouseButtonEventArgs e) { // Ignore actions if the button down arises from a different presentation source if (!PresentationSource.UnderSamePresentationSource(e.OriginalSource as DependencyObject, this)) { return; } DataGridRow rowOwner = DataGridRowOwner; DataGrid dataGridOwner = rowOwner != null ? rowOwner.DataGridOwner : null; if ((dataGridOwner != null) && (rowOwner != null)) { // HandleSelectionForRowHeaderAndDetailsInput below sets the CurrentCell // of datagrid to the cell with displayindex 0 in the row. // This implicitly queues a request to MakeVisible command // of ScrollViewer. The command handler calls MakeVisible method of // VirtualizingStackPanel (of rows presenter) which works only // when the visual's parent layout is clean. DataGridCellsPanel layout is // not clean as per MakeVisible of VSP becuase we distribute the layout of cells for the // sake of row headers and hence it fails. VSP.MakeVisible method requeues a request to // ScrollViewer.MakeVisible command hence resulting into an infinite loop. // The workaround is to bring the concerned cell into the view by calling // ScrollIntoView so that by the time MakeVisible handler of ScrollViewer is // executed the cell is already visible and the handler succeeds. if (dataGridOwner.CurrentCell.Item != rowOwner.Item) { dataGridOwner.ScrollIntoView(rowOwner.Item, dataGridOwner.ColumnFromDisplayIndex(0)); } dataGridOwner.HandleSelectionForRowHeaderAndDetailsInput(rowOwner, /* startDragging = */ Mouse.Captured == null); } } internal FrameworkElement DetailsElement { get { var childrenCount = VisualTreeHelper.GetChildrenCount(this); if (childrenCount > 0) { return VisualTreeHelper.GetChild(this, 0) as FrameworkElement; } return null; } } ////// Update all properties that get a value from the DataGrid /// ////// See comment on DataGridRow.OnDataGridChanged /// internal void SyncProperties() { DataGridRow owner = DataGridRowOwner; Content = owner != null ? owner.Item : null; DataGridHelper.TransferProperty(this, ContentTemplateProperty); DataGridHelper.TransferProperty(this, ContentTemplateSelectorProperty); } #endregion #region Notification Propagation ////// Notifies parts that respond to changes in the properties. /// private static void OnNotifyPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ((DataGridDetailsPresenter)d).NotifyPropertyChanged(d, e); } internal void NotifyPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (e.Property == DataGrid.RowDetailsTemplateProperty || e.Property == DataGridRow.DetailsTemplateProperty || e.Property == ContentTemplateProperty) { DataGridHelper.TransferProperty(this, ContentTemplateProperty); } else if (e.Property == DataGrid.RowDetailsTemplateSelectorProperty || e.Property == DataGridRow.DetailsTemplateSelectorProperty || e.Property == ContentTemplateSelectorProperty) { DataGridHelper.TransferProperty(this, ContentTemplateSelectorProperty); } } #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 (row.DetailsPresenterDrawsGridLines && 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 (row.DetailsPresenterDrawsGridLines && 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 (row.DetailsPresenterDrawsGridLines && 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 Helpers ////// The DataGrid that owns this control /// private DataGrid DataGridOwner { get { DataGridRow owner = DataGridRowOwner; if (owner != null) { return owner.DataGridOwner; } return null; } } ////// The DataGridRow that owns this control. /// internal DataGridRow DataGridRowOwner { get { return DataGridHelper.FindParent(this); } } #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.Diagnostics; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; namespace System.Windows.Controls.Primitives { public class DataGridDetailsPresenter : ContentPresenter { static DataGridDetailsPresenter() { DefaultStyleKeyProperty.OverrideMetadata(typeof(DataGridDetailsPresenter), new FrameworkPropertyMetadata(typeof(DataGridDetailsPresenter))); ContentTemplateProperty.OverrideMetadata(typeof(DataGridDetailsPresenter), new FrameworkPropertyMetadata(OnNotifyPropertyChanged, OnCoerceContentTemplate)); ContentTemplateSelectorProperty.OverrideMetadata(typeof(DataGridDetailsPresenter), new FrameworkPropertyMetadata(OnNotifyPropertyChanged, OnCoerceContentTemplateSelector)); EventManager.RegisterClassHandler(typeof(DataGridDetailsPresenter), MouseLeftButtonDownEvent, new MouseButtonEventHandler(OnAnyMouseLeftButtonDownThunk), true); } /// /// Instantiates a new instance of this class. /// public DataGridDetailsPresenter() { } #region Automation protected override System.Windows.Automation.Peers.AutomationPeer OnCreateAutomationPeer() { return new System.Windows.Automation.Peers.DataGridDetailsPresenterAutomationPeer(this); } #endregion #region Coercion ////// Coerces the ContentTemplate property. /// private static object OnCoerceContentTemplate(DependencyObject d, object baseValue) { var details = d as DataGridDetailsPresenter; var row = details.DataGridRowOwner; var dataGrid = row != null ? row.DataGridOwner : null; return DataGridHelper.GetCoercedTransferPropertyValue( details, baseValue, ContentTemplateProperty, row, DataGridRow.DetailsTemplateProperty, dataGrid, DataGrid.RowDetailsTemplateProperty); } ////// Coerces the ContentTemplateSelector property. /// private static object OnCoerceContentTemplateSelector(DependencyObject d, object baseValue) { var details = d as DataGridDetailsPresenter; var row = details.DataGridRowOwner; var dataGrid = row != null ? row.DataGridOwner : null; return DataGridHelper.GetCoercedTransferPropertyValue( details, baseValue, ContentTemplateSelectorProperty, row, DataGridRow.DetailsTemplateSelectorProperty, dataGrid, DataGrid.RowDetailsTemplateSelectorProperty); } #endregion #region Row Communication protected internal override void OnVisualParentChanged(DependencyObject oldParent) { base.OnVisualParentChanged(oldParent); // DataGridRow.DetailsPresenter is used by automation peers // Give the Row a pointer to the RowHeader so that it can propagate down change notifications DataGridRow owner = DataGridRowOwner; if (owner != null) { owner.DetailsPresenter = this; // At the time that a Row is prepared we can't [....] because the DetailsPresenter isn't created yet. // Doing it here ensures that the DetailsPresenter is in the visual tree. SyncProperties(); } } private static void OnAnyMouseLeftButtonDownThunk(object sender, MouseButtonEventArgs e) { ((DataGridDetailsPresenter)sender).OnAnyMouseLeftButtonDown(e); } private void OnAnyMouseLeftButtonDown(System.Windows.Input.MouseButtonEventArgs e) { // Ignore actions if the button down arises from a different presentation source if (!PresentationSource.UnderSamePresentationSource(e.OriginalSource as DependencyObject, this)) { return; } DataGridRow rowOwner = DataGridRowOwner; DataGrid dataGridOwner = rowOwner != null ? rowOwner.DataGridOwner : null; if ((dataGridOwner != null) && (rowOwner != null)) { // HandleSelectionForRowHeaderAndDetailsInput below sets the CurrentCell // of datagrid to the cell with displayindex 0 in the row. // This implicitly queues a request to MakeVisible command // of ScrollViewer. The command handler calls MakeVisible method of // VirtualizingStackPanel (of rows presenter) which works only // when the visual's parent layout is clean. DataGridCellsPanel layout is // not clean as per MakeVisible of VSP becuase we distribute the layout of cells for the // sake of row headers and hence it fails. VSP.MakeVisible method requeues a request to // ScrollViewer.MakeVisible command hence resulting into an infinite loop. // The workaround is to bring the concerned cell into the view by calling // ScrollIntoView so that by the time MakeVisible handler of ScrollViewer is // executed the cell is already visible and the handler succeeds. if (dataGridOwner.CurrentCell.Item != rowOwner.Item) { dataGridOwner.ScrollIntoView(rowOwner.Item, dataGridOwner.ColumnFromDisplayIndex(0)); } dataGridOwner.HandleSelectionForRowHeaderAndDetailsInput(rowOwner, /* startDragging = */ Mouse.Captured == null); } } internal FrameworkElement DetailsElement { get { var childrenCount = VisualTreeHelper.GetChildrenCount(this); if (childrenCount > 0) { return VisualTreeHelper.GetChild(this, 0) as FrameworkElement; } return null; } } ////// Update all properties that get a value from the DataGrid /// ////// See comment on DataGridRow.OnDataGridChanged /// internal void SyncProperties() { DataGridRow owner = DataGridRowOwner; Content = owner != null ? owner.Item : null; DataGridHelper.TransferProperty(this, ContentTemplateProperty); DataGridHelper.TransferProperty(this, ContentTemplateSelectorProperty); } #endregion #region Notification Propagation ////// Notifies parts that respond to changes in the properties. /// private static void OnNotifyPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ((DataGridDetailsPresenter)d).NotifyPropertyChanged(d, e); } internal void NotifyPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (e.Property == DataGrid.RowDetailsTemplateProperty || e.Property == DataGridRow.DetailsTemplateProperty || e.Property == ContentTemplateProperty) { DataGridHelper.TransferProperty(this, ContentTemplateProperty); } else if (e.Property == DataGrid.RowDetailsTemplateSelectorProperty || e.Property == DataGridRow.DetailsTemplateSelectorProperty || e.Property == ContentTemplateSelectorProperty) { DataGridHelper.TransferProperty(this, ContentTemplateSelectorProperty); } } #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 (row.DetailsPresenterDrawsGridLines && 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 (row.DetailsPresenterDrawsGridLines && 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 (row.DetailsPresenterDrawsGridLines && 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 Helpers ////// The DataGrid that owns this control /// private DataGrid DataGridOwner { get { DataGridRow owner = DataGridRowOwner; if (owner != null) { return owner.DataGridOwner; } return null; } } ////// The DataGridRow that owns this control. /// internal DataGridRow DataGridRowOwner { get { return DataGridHelper.FindParent(this); } } #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
- XpsPackagingPolicy.cs
- QuaternionRotation3D.cs
- BatchStream.cs
- LambdaCompiler.Address.cs
- DetailsViewActionList.cs
- TextTreePropertyUndoUnit.cs
- QueryCursorEventArgs.cs
- RpcCryptoRequest.cs
- GeneralTransform3D.cs
- HttpServerVarsCollection.cs
- Margins.cs
- DataGridDefaultColumnWidthTypeConverter.cs
- PauseStoryboard.cs
- XslVisitor.cs
- GcHandle.cs
- TextServicesCompartmentEventSink.cs
- ChannelRequirements.cs
- SamlAuthenticationClaimResource.cs
- StatusBarDrawItemEvent.cs
- MessageEncoderFactory.cs
- FaultDescription.cs
- HealthMonitoringSection.cs
- StrongNamePublicKeyBlob.cs
- Expander.cs
- EmptyReadOnlyDictionaryInternal.cs
- MailMessageEventArgs.cs
- ConfigurationLockCollection.cs
- InternalCache.cs
- HwndSourceKeyboardInputSite.cs
- DeferredElementTreeState.cs
- StrongNameMembershipCondition.cs
- SspiSafeHandles.cs
- ProcessProtocolHandler.cs
- EarlyBoundInfo.cs
- OleDbEnumerator.cs
- TreeChangeInfo.cs
- ListControlBuilder.cs
- BamlTreeUpdater.cs
- MonitorWrapper.cs
- LoadGrammarCompletedEventArgs.cs
- SynchronousChannel.cs
- DateTimeSerializationSection.cs
- FixedTextBuilder.cs
- EmulateRecognizeCompletedEventArgs.cs
- DynamicResourceExtension.cs
- AsymmetricSignatureFormatter.cs
- ListBoxItemWrapperAutomationPeer.cs
- ApplyHostConfigurationBehavior.cs
- PcmConverter.cs
- TcpTransportSecurity.cs
- MimeWriter.cs
- InstanceView.cs
- ActiveXHost.cs
- XmlAttributeProperties.cs
- ChildTable.cs
- CfgParser.cs
- StagingAreaInputItem.cs
- RelationshipEndCollection.cs
- TypeDescriptorContext.cs
- LambdaCompiler.Binary.cs
- HitTestWithPointDrawingContextWalker.cs
- DesignerActionPanel.cs
- LineSegment.cs
- StaticDataManager.cs
- SiteMapHierarchicalDataSourceView.cs
- BitmapEffectGeneralTransform.cs
- NotificationContext.cs
- BitmapSizeOptions.cs
- WorkflowRuntimeServiceElement.cs
- XmlMtomWriter.cs
- Image.cs
- WeakEventTable.cs
- ScrollChangedEventArgs.cs
- TableDetailsRow.cs
- FastPropertyAccessor.cs
- CustomCredentialPolicy.cs
- StreamInfo.cs
- QilExpression.cs
- CaseInsensitiveComparer.cs
- controlskin.cs
- MemoryStream.cs
- AppAction.cs
- XmlComment.cs
- grammarelement.cs
- DynamicUpdateCommand.cs
- ByteAnimationUsingKeyFrames.cs
- Main.cs
- SqlBuilder.cs
- EdgeProfileValidation.cs
- IisNotInstalledException.cs
- DesignerDataParameter.cs
- BaseAddressPrefixFilterElementCollection.cs
- CodeParameterDeclarationExpressionCollection.cs
- XhtmlBasicValidationSummaryAdapter.cs
- ExpressionBindingCollection.cs
- FrameSecurityDescriptor.cs
- ThemeDictionaryExtension.cs
- XmlArrayAttribute.cs
- SineEase.cs
- OracleBFile.cs