Пример #1
0
        /// <summary>
        /// Create a visual element based on the properties of the column.
        /// </summary>
        /// <param name="columnViewColumn">The column that defines the cell.</param>
        /// <returns>A visual element that holds the content of the cell.</returns>
        public static FrameworkElement CreateCell(ColumnViewColumn columnViewColumn)
        {
            // Validate the parameters.
            if (columnViewColumn == null)
            {
                throw new ArgumentNullException("columnViewColumn");
            }

            // This will either create an element based on the templates associated with the ColumnViewColumn, or for simple binding, will create a simple cell and
            // bind it using the binding provided in the DisplayMemberBinding property.  Both variations return a FrameworkElement that is used as an element in the
            // row to display the data associated with the column.
            FrameworkElement frameworkElement;

            if (columnViewColumn.DisplayMemberBinding == null)
            {
                // This will create a generic ContentPresenter using the templates associated with the ColumnView and bind the content of the generic control to
                // the data context (which contains the row data).  It is the responsibility of the cell to select which property of the row data it wants to
                // display.  It is important to remember that a ContentPresenter is not like other controls.  The DataContext is not inheritied from the logical
                // parent, it is set to the  Content property of the ContentPresenter.  The main problem we're solving here is that the child control that's
                // generated from the ContentPresenter's template needs a DataContext, but the ContentPresenter doesn't have one since it's pointing to itself.  To
                // solve this, we'll bind the Content of the ContentPresenter to the ColumnViewRowPresenter that is it's parent.  This effectively restores the
                // DataContext inheritance that all other controls have.  Clear as mud?
                ContentPresenter contentPresenter = new ContentPresenter();
                contentPresenter.ContentTemplate         = columnViewColumn.CellTemplate;
                contentPresenter.ContentTemplateSelector = columnViewColumn.CellTemplateSelector;
                Binding dataContextBinding = new Binding()
                {
                    Path = new PropertyPath("DataContext")
                };
                dataContextBinding.RelativeSource = new RelativeSource(RelativeSourceMode.FindAncestor, typeof(ColumnViewRowPresenter), 1);
                BindingOperations.SetBinding(contentPresenter, ContentPresenter.ContentProperty, dataContextBinding);
                frameworkElement = contentPresenter;
            }
            else
            {
                // This will create a cell to display the data provided by the 'DisplayMemberBinding' which selects which property of the row data is to be
                // displayed.
                ColumnViewColumnCell columnViewColumnCell = new ColumnViewColumnCell();
                BindingOperations.SetBinding(columnViewColumnCell, ColumnViewColumnCell.ContentProperty, columnViewColumn.DisplayMemberBinding);
                frameworkElement = columnViewColumnCell;
            }

            // This element is used to present the data.
            return(frameworkElement);
        }
Пример #2
0
        /// <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;
                }
            }
        }