/// <summary> /// Handles a change to the column property. /// </summary> /// <param name="sender">The Object that originated the event.</param> /// <param name="propertyChangedEventArgs">The event arguments.</param> protected override void OnColumnPropertyChanged(Object sender, PropertyChangedEventArgs propertyChangedEventArgs) { // Validate the parameters. if (sender == null) { throw new ArgumentNullException("sender"); } if (propertyChangedEventArgs == null) { throw new ArgumentNullException("propertyChangedEventArgs"); } // This will get the column where the property change occurred from the sender. ColumnViewColumn columnViewColumn = sender as ColumnViewColumn; // If the column is visible, then it has a visual element which needs to have its properties reconciled with the ColumnViewColumn properties. if (columnViewColumn.IsVisible) { // This will find the visual element what has properites that must be reconciled with the header. Int32 columnIndex = this.Columns.IndexOf(columnViewColumn); ColumnViewColumnCell columnViewColumnCell = this.Children[columnIndex] as ColumnViewColumnCell; // This will apply the property in the column to the visual element representing that column in the current row. switch (propertyChangedEventArgs.PropertyName) { case "CellTemplate": case "CellTemplateSelector": case "DisplayMemberBinding": // Recreate the cell based on the new properties. this.Children.RemoveAt(columnIndex); FrameworkElement frameworkElement = ColumnViewRowPresenter.CreateCell(columnViewColumn); this.InstallCell(frameworkElement, columnViewColumn); this.Children.Insert(columnIndex, frameworkElement); break; case "Width": case "MinWidth": // Forcing a re-measurement of the row will pick up the changes made to the column's width. this.InvalidateMeasure(); break; } } }
/// <summary> /// Handles a change to the column collection. /// </summary> /// <param name="notifyCollectionChangedEventArgs">The Object that originated the event.</param> /// <param name="notifyCollectionChangedEventArgs">Provides data for the CollectionChanged event.</param> protected override void OnColumnCollectionChanged(Object sender, NotifyCollectionChangedEventArgs notifyCollectionChangedEventArgs) { Int32 columnIndex; // Validate the parameters. if (sender == null) { throw new ArgumentNullException("sender"); } if (notifyCollectionChangedEventArgs == null) { throw new ArgumentNullException("notifyCollectionChangedEventArgs"); } // This will reconcile the visual elements in this control with the definition of the columns. switch (notifyCollectionChangedEventArgs.Action) { case NotifyCollectionChangedAction.Add: // Create a cell to hold the value and add each it to the row at the given index. columnIndex = notifyCollectionChangedEventArgs.NewStartingIndex == -1 ? 0 : notifyCollectionChangedEventArgs.NewStartingIndex; foreach (ColumnViewColumn columnViewColumn in notifyCollectionChangedEventArgs.NewItems) { if (columnViewColumn.IsVisible) { FrameworkElement frameworkElement = ColumnViewRowPresenter.CreateCell(columnViewColumn); this.InstallCell(frameworkElement, columnViewColumn); this.Children.Insert(columnIndex++, frameworkElement); } this.InvalidateMeasure(); } break; case NotifyCollectionChangedAction.Move: // Columns that appear after the visible count in the collection are hidden items. They exist only as a pool of potential columns. The items below // the 'VisibleCount' are actually visible in this view and appear in the same order in which they appear in this control. As items are moved in // and out of the visible range, we will create or destroy the visual elements used to show those columns in the viewer. Int32 oldIndex = notifyCollectionChangedEventArgs.OldStartingIndex; Int32 newIndex = notifyCollectionChangedEventArgs.NewStartingIndex; ColumnViewColumn movedColumn = this.Columns[newIndex]; if (this.Children.Count == this.Columns.VisibleCount) { // At this point, the collection hasn't changed. We are just moving columns around. UIElement uiElement = this.Children[oldIndex]; this.Children.RemoveAt(notifyCollectionChangedEventArgs.OldStartingIndex); this.Children.Insert(notifyCollectionChangedEventArgs.NewStartingIndex, uiElement); this.InvalidateArrange(); } else { // This will hide the column by destroying the visual elements used to display the column. if (oldIndex < this.Children.Count) { this.Children.RemoveAt(oldIndex); } // This will create a visual element to display the now visible column. if (movedColumn.IsVisible) { FrameworkElement frameworkElement = ColumnViewRowPresenter.CreateCell(movedColumn); this.InstallCell(frameworkElement, movedColumn); this.Children.Insert(newIndex, frameworkElement); } } break; case NotifyCollectionChangedAction.Remove: // Remove the offending cells from the specified location. columnIndex = notifyCollectionChangedEventArgs.OldStartingIndex; foreach (ColumnViewColumn columnViewColumn in notifyCollectionChangedEventArgs.OldItems) { this.RemoveCell(columnIndex++); } break; case NotifyCollectionChangedAction.Reset: // Clear them all. while (this.Children.Count != 0) { this.RemoveCell(0); } break; } }