/// <summary> /// Fired when the Row is attached to the DataGrid. The scenario here is if the user is scrolling and /// the Row is a recycled container that was just added back to the visual tree. Properties that rely on a value from /// the Grid should be reevaluated because they may be stale. /// </summary> /// <remarks> /// Properties can obviously be stale if the DataGrid's value changes while the row is disconnected. They can also /// be stale for unobvious reasons. /// /// For example, the Style property is invalidated when we detect a new Visual parent. This happens for /// elements in the row (such as the RowHeader) before Prepare is called on the Row. The coercion callback /// will thus be unable to find the DataGrid and will return the wrong value. /// /// There is a potential for perf work here. If we know a DP isn't invalidated when the visual tree is reconnected /// and we know that the Grid hasn't modified that property then its value is likely fine. We could also cache whether /// or not the Grid's property is the one that's winning. If not, no need to redo the coercion. This notification /// is pretty fast already and thus not worth the work for now. /// </remarks> private void SyncProperties(bool forcePrepareCells) { // Coerce all properties on Row that depend on values from the DataGrid // Style is ok since it's equivalent to ItemContainerStyle and has already been invalidated. DataGridHelper.TransferProperty(this, BackgroundProperty); DataGridHelper.TransferProperty(this, HeaderStyleProperty); DataGridHelper.TransferProperty(this, HeaderTemplateProperty); DataGridHelper.TransferProperty(this, HeaderTemplateSelectorProperty); DataGridHelper.TransferProperty(this, ValidationErrorTemplateProperty); DataGridHelper.TransferProperty(this, DetailsTemplateProperty); DataGridHelper.TransferProperty(this, DetailsTemplateSelectorProperty); DataGridHelper.TransferProperty(this, DetailsVisibilityProperty); CoerceValue(VisibilityProperty); // Handle NewItemPlaceholder case RestoreAttachedItemValue(this, DetailsVisibilityProperty); var cellsPresenter = CellsPresenter; if (cellsPresenter != null) { cellsPresenter.SyncProperties(forcePrepareCells); RestoreAttachedItemValue(cellsPresenter, DataGridCellsPresenter.HeightProperty); } if (DetailsPresenter != null) { DetailsPresenter.SyncProperties(); } if (RowHeader != null) { RowHeader.SyncProperties(); } }
/// <summary> /// General notification for DependencyProperty changes from the grid or from columns. /// </summary> internal void NotifyPropertyChanged(DependencyObject d, string propertyName, DependencyPropertyChangedEventArgs e, NotificationTarget target) { if (DataGridHelper.ShouldNotifyRows(target)) { if (e.Property == DataGrid.RowBackgroundProperty || e.Property == DataGrid.AlternatingRowBackgroundProperty || e.Property == BackgroundProperty || e.Property == AlternationIndexProperty) { DataGridHelper.TransferProperty(this, BackgroundProperty); } else if (e.Property == DataGrid.RowHeaderStyleProperty || e.Property == HeaderStyleProperty) { DataGridHelper.TransferProperty(this, HeaderStyleProperty); } else if (e.Property == DataGrid.RowHeaderTemplateProperty || e.Property == HeaderTemplateProperty) { DataGridHelper.TransferProperty(this, HeaderTemplateProperty); } else if (e.Property == DataGrid.RowHeaderTemplateSelectorProperty || e.Property == HeaderTemplateSelectorProperty) { DataGridHelper.TransferProperty(this, HeaderTemplateSelectorProperty); } else if (e.Property == DataGrid.RowValidationErrorTemplateProperty || e.Property == ValidationErrorTemplateProperty) { DataGridHelper.TransferProperty(this, ValidationErrorTemplateProperty); } else if (e.Property == DataGrid.RowDetailsTemplateProperty || e.Property == DetailsTemplateProperty) { DataGridHelper.TransferProperty(this, DetailsTemplateProperty); DataGridHelper.TransferProperty(this, DetailsVisibilityProperty); } else if (e.Property == DataGrid.RowDetailsTemplateSelectorProperty || e.Property == DetailsTemplateSelectorProperty) { DataGridHelper.TransferProperty(this, DetailsTemplateSelectorProperty); DataGridHelper.TransferProperty(this, DetailsVisibilityProperty); } else if (e.Property == DataGrid.RowDetailsVisibilityModeProperty || e.Property == DetailsVisibilityProperty || e.Property == IsSelectedProperty) { DataGridHelper.TransferProperty(this, DetailsVisibilityProperty); } else if (e.Property == ItemProperty) { OnItemChanged(e.OldValue, e.NewValue); } else if (e.Property == HeaderProperty) { OnHeaderChanged(e.OldValue, e.NewValue); } else if (e.Property == BindingGroupProperty) { // Re-run validation, but wait until Binding has occured. Dispatcher.BeginInvoke(new DispatcherOperationCallback(DelayedValidateWithoutUpdate), DispatcherPriority.DataBind, e.NewValue); } } if (DataGridHelper.ShouldNotifyDetailsPresenter(target)) { if (DetailsPresenter != null) { DetailsPresenter.NotifyPropertyChanged(d, e); } } if (DataGridHelper.ShouldNotifyCellsPresenter(target) || DataGridHelper.ShouldNotifyCells(target) || DataGridHelper.ShouldRefreshCellContent(target)) { DataGridCellsPresenter cellsPresenter = CellsPresenter; if (cellsPresenter != null) { cellsPresenter.NotifyPropertyChanged(d, propertyName, e, target); } } if (DataGridHelper.ShouldNotifyRowHeaders(target) && RowHeader != null) { RowHeader.NotifyPropertyChanged(d, e); } }