/Xceed.Silverlight.DataGrid/(BaseOM)/DataGridPanel.cs
C# | 453 lines | 322 code | 96 blank | 35 comment | 24 complexity | a67311f4e3cac2a75dedaa5a605afe91 MD5 | raw file
- /************************************************************************
-
- Extended Silverlight Toolkit
-
- Copyright (C) 2010-2012 Xceed Software Inc.
-
- This program is provided to you under the terms of the Microsoft Public
- License (Ms-PL) as published at http://extendedsilverlight.codeplex.com/license
-
- Please purchase a commercial version of this toolkit if you are using
- it in a commercial product. The commercial versions support the project,
- and also include more features for each control, priority support,
- source code, updates, removed watermark, and a proprietary license.
-
- Visit http://xceed.com and follow @datagrid on Twitter.
-
- **********************************************************************/
-
- using System;
- using System.Collections.Generic;
- using System.Diagnostics;
- using System.Linq;
- using System.Windows;
- using System.Windows.Controls;
- using Xceed.Silverlight.Utils;
- using Xceed.Utils.Licensing;
- using Xceed.Silverlight.Compatibility;
-
- namespace Xceed.Silverlight.DataGrid
- {
- internal class DataGridPanel : Panel, IColumnPanelOwner, IXceedRoutedEventElement, IVisitorElement
- {
- #region Static Fields
-
- internal static readonly XceedRoutedEvent ColumnAdded = new XceedRoutedEvent();
- internal static readonly XceedRoutedEvent ColumnRemoved = new XceedRoutedEvent();
-
- #endregion
-
- #region Constructor
-
- public DataGridPanel()
- {
- m_eventHelper = new XceedEventHelper( this );
- m_columnPanel = new ColumnPanel( this );
- this.Children.Add( new RootHost() );
- }
-
- #endregion
-
- #region RenderedColumns Internal Property
-
- internal IEnumerable<ColumnContainer> RenderedColumns
- {
- get
- {
- return this.ColumnPanel.RenderedColumns;
- }
- }
-
- #endregion
-
- #region AllColumns Internal Property
-
- internal IEnumerable<ColumnContainer> AllColumns
- {
- get
- {
- return this.ColumnPanel.AllColumns;
- }
- }
-
- #endregion
-
- #region ColumnPanel Internal Property
-
- internal ColumnPanel ColumnPanel
- {
- get
- {
- return m_columnPanel;
- }
- }
-
- #endregion
-
- #region EventManager Internal Property
-
- internal XceedEventHelper EventManager
- {
- [DebuggerStepThrough]
- get
- {
- return m_eventHelper;
- }
- }
-
- private readonly XceedEventHelper m_eventHelper;
-
- #endregion
-
- #region RootHost Internal Property
-
- internal RootHost RootHost
- {
- get
- {
- return ( RootHost )this.Children[ this.RootContainerIndex ];
- }
- }
-
- #endregion
-
- #region FixedHeaders Internal Property
-
- internal IEnumerable<UIElement> FixedHeaders
- {
- get
- {
- return CompatibilityUtils.GetEnumerable(this.Children)
- .Take( this.RootContainerIndex );
- }
- }
-
- #endregion
-
- #region FixedFooters Internal Property
-
- internal IEnumerable<UIElement> FixedFooters
- {
- get
- {
- return CompatibilityUtils.GetEnumerable(this.Children)
- .Skip( this.RootContainerIndex + 1 );
- }
- }
-
- #endregion
-
- #region RootContainerIndex Internal Property
-
- internal int RootContainerIndex
- {
- get
- {
- for(int i=0;i<this.Children.Count;i++)
- {
- if( this.Children[i] is RootHost )
- return i;
- }
-
- throw new DataGridInternalException();
- }
- }
-
- #endregion
-
- #region PendingTransitionContext Internal Property
-
- internal TransitionContext PendingTransitionContext
- {
- get;
- set;
- }
-
- #endregion
-
- #region ColumnElementHosts Internal Property
-
- internal IEnumerable<IColumnElementHost> ColumnElementHosts
- {
- get
- {
- ColumnElementHostExtractorVisitor visitor = new ColumnElementHostExtractorVisitor();
- this.Accept( visitor );
- // Do not return the visitor.Host collection. We want the returned IEnumerable
- // to be dynamic and recalculated on each enumration.
- foreach( IColumnElementHost host in visitor.Hosts )
- {
- yield return host;
- }
- }
- }
-
- #endregion
-
- #region ColumnPanelMeasureManager Private Property
-
- private IManageColumnsMeasure ColumnPanelMeasureManager
- {
- get
- {
- return ( IManageColumnsMeasure )this.GetElementOrParentBase<IManageColumnsMeasure>();
- }
- }
-
- #endregion
-
- #region UnconstrainedStateChanged Internal Event
-
- internal event EventHandler UnconstrainedStateChanged;
-
- private void OnUnconstrainedStateChanged()
- {
- if( this.UnconstrainedStateChanged != null )
- {
- this.UnconstrainedStateChanged( this, EventArgs.Empty );
- }
- }
-
- #endregion
-
- protected override Size MeasureOverride( Size availableSize )
- {
- bool isInDesign = DesignerProperties.GetIsInDesignMode();
-
- if( double.IsInfinity( availableSize.Width ) || double.IsNaN( availableSize.Width ) )
- {
- //If in an unconstrained environement and debugging
- if( !isInDesign && Debugger.IsAttached )
- {
- //Warn the developer the size of the grid has been arbitrary fixed.
- this.OnUnconstrainedStateChanged();
- }
-
- //Temporary value for design time purpose.
- availableSize.Width = 640d;
- }
-
- if( double.IsInfinity( availableSize.Height ) || double.IsNaN( availableSize.Height ) )
- {
- //If in an unconstrained environement and debugging
- if( !isInDesign && Debugger.IsAttached )
- {
- //Warn the developer the size of the grid has been arbitrary fixed.
- this.OnUnconstrainedStateChanged();
- }
-
- //Temporary value for design time purpose.
- availableSize.Height = 480d;
- }
-
- double columnPanelWidth = this.ColumnPanelMeasureManager.OnMeasureOverride( availableSize ).Width;
-
- //Invalidate the measure of all the column element hosts in order
- //to have the cells not clipped when the ColumnWidth changes.
- this.InvalidateColumnHostsMeasure();
-
- Size measuredSize = new Size( Math.Min( columnPanelWidth, availableSize.Width) , 0 );
- int rootContainerIndex = this.RootContainerIndex;
-
- Action<int> measureChild = (i) =>
- {
- UIElement child = this.Children[ i ];
- child.Measure( availableSize );
- availableSize.Height = Math.Max( 0d, availableSize.Height - child.DesiredSize.Height );
- measuredSize.Height += child.DesiredSize.Height;
- };
-
- //Measure FixedHeaders
- for( int i = 0; i < rootContainerIndex; i++ )
- {
- measureChild( i );
- }
-
- //Measure FixedFooters
- for( int i = rootContainerIndex+1; i < this.Children.Count; i++ )
- {
- measureChild( i );
- }
-
- RootHost rootContainer = ( RootHost )this.Children[ rootContainerIndex ];
-
- //Measure the RootContainer
- rootContainer.Measure( availableSize );
-
- Size containerSize = rootContainer.DesiredSize;
- measuredSize.Height += Math.Min( availableSize.Height, containerSize.Height );
-
- return measuredSize;
- }
-
- protected override Size ArrangeOverride( Size finalSize )
- {
- int rootContainerIndex = this.RootContainerIndex;
-
- m_columnPanel.Arrange( finalSize, new LayoutParameters( this.PendingTransitionContext ) );
- this.PendingTransitionContext = null;
-
- //Invalidte the arrange of all the column elements hosts in order
- //to have the cells layouted
- this.InvalidateColumnHostsArrange();
-
- double headersArrangeHeight = 0;
- double footersArrangeHeight = 0;
- Rect finalRect = new Rect( new Point( 0, 0 ), finalSize );
- for( int i = 0; i < rootContainerIndex; i++ )
- {
- UIElement child = this.Children[ i ];
- finalRect.Height = child.DesiredSize.Height;
- child.Arrange( finalRect );
- finalRect.Y += finalRect.Height;
- headersArrangeHeight += finalRect.Height;
- }
-
- finalRect = new Rect( new Point( 0, finalSize.Height ), finalSize );
- for( int i = this.Children.Count - 1; i > rootContainerIndex; i-- )
- {
- UIElement child = this.Children[ i ];
- finalRect.Height = child.DesiredSize.Height;
- finalRect.Y -= finalRect.Height;
- child.Arrange( finalRect );
- footersArrangeHeight += finalRect.Height;
- }
-
-
- finalRect = new Rect( 0,
- headersArrangeHeight,
- finalSize.Width,
- Math.Max( 0d, finalSize.Height - headersArrangeHeight - footersArrangeHeight ) );
-
- this.Children[rootContainerIndex].Arrange( finalRect );
-
- return finalSize;
- }
-
- internal void Accept( IVisitor visitor )
- {
- visitor.Visit( this );
- }
-
- internal void EndTransition()
- {
- this.ColumnPanel.EndTransition();
-
- this.InvalidateColumnHostsArrange();
- }
-
- internal void SetHeadersFooters( IList<UIElement> headers, IList<UIElement> footers )
- {
- //Remove all but the RootContainer
- int rootContainerIndex = this.RootContainerIndex;
- int headersCount = this.RootContainerIndex;
- int footersCount = this.Children.Count - this.RootContainerIndex - 1;
-
- bool updateHeaders = !this.FixedHeaders.SequenceEqual(headers);
- bool updateFooters = !this.FixedFooters.SequenceEqual(footers);
-
- if(updateHeaders)
- {
- //Remove current headers
- for(int i=0;i<headersCount;i++)
- {
- this.Children.RemoveAt(0);
- }
- headersCount = 0;
- }
-
- if(updateFooters)
- {
- //Remove current footers
- for( int i = 0; i < footersCount; i++ )
- {
- this.Children.RemoveAt(headersCount + 1);
- }
- }
-
- if(updateHeaders)
- {
- for(int i=0;i<headers.Count;i++)
- {
- this.Children.Insert(i,headers[i]);
- }
- }
-
- if(updateFooters)
- {
- for(int i=0;i<footers.Count;i++)
- {
- this.Children.Add(footers[i]);
- }
- }
- }
-
- private void InvalidateColumnHostsMeasure()
- {
- foreach( IColumnElementHost host in this.ColumnElementHosts )
- {
- host.InvalidateColumnMeasure();
- }
- }
-
- private void InvalidateColumnHostsArrange()
- {
- foreach( IColumnElementHost host in this.ColumnElementHosts )
- {
- host.InvalidateColumnArrange();
- }
- }
-
- #region IVisitorElement Members
-
- void IVisitorElement.Accept( IVisitor visitor )
- {
- this.Accept( visitor );
- }
-
- #endregion
-
- #region IColumnPanelOwner Members
-
- void IColumnPanelOwner.OnColumnAdded( ColumnContainer added )
- {
- this.EventManager.RaiseEvent( DataGridPanel.ColumnAdded, new ColumnContainerEventArgs( this, added ) );
- }
-
- void IColumnPanelOwner.OnColumnRemoved( ColumnContainer removed )
- {
- this.EventManager.RaiseEvent( DataGridPanel.ColumnRemoved, new ColumnContainerEventArgs( this, removed ) );
- }
-
- void IColumnPanelOwner.InvalidatePanelMeasure()
- {
- this.InvalidateMeasure();
- }
-
- void IColumnPanelOwner.InvalidatePanelArrange()
- {
- this.InvalidateArrange();
- }
-
- #endregion
-
- #region IXceedRoutedEventElement Members
-
- XceedEventHelper IXceedRoutedEventElement.EventManager
- {
- [DebuggerStepThrough]
- get
- {
- return this.EventManager;
- }
- }
-
- #endregion
-
- #region Private Fields
-
- private readonly ColumnPanel m_columnPanel;
-
- #endregion
- }
- }