PageRenderTime 25ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/Xceed.Silverlight.DataGrid/(BaseOM)/DataGridPanel.cs

http://extendedsilverlight.codeplex.com
C# | 453 lines | 322 code | 96 blank | 35 comment | 24 complexity | a67311f4e3cac2a75dedaa5a605afe91 MD5 | raw file
  1. /************************************************************************
  2. Extended Silverlight Toolkit
  3. Copyright (C) 2010-2012 Xceed Software Inc.
  4. This program is provided to you under the terms of the Microsoft Public
  5. License (Ms-PL) as published at http://extendedsilverlight.codeplex.com/license
  6. Please purchase a commercial version of this toolkit if you are using
  7. it in a commercial product. The commercial versions support the project,
  8. and also include more features for each control, priority support,
  9. source code, updates, removed watermark, and a proprietary license.
  10. Visit http://xceed.com and follow @datagrid on Twitter.
  11. **********************************************************************/
  12. using System;
  13. using System.Collections.Generic;
  14. using System.Diagnostics;
  15. using System.Linq;
  16. using System.Windows;
  17. using System.Windows.Controls;
  18. using Xceed.Silverlight.Utils;
  19. using Xceed.Utils.Licensing;
  20. using Xceed.Silverlight.Compatibility;
  21. namespace Xceed.Silverlight.DataGrid
  22. {
  23. internal class DataGridPanel : Panel, IColumnPanelOwner, IXceedRoutedEventElement, IVisitorElement
  24. {
  25. #region Static Fields
  26. internal static readonly XceedRoutedEvent ColumnAdded = new XceedRoutedEvent();
  27. internal static readonly XceedRoutedEvent ColumnRemoved = new XceedRoutedEvent();
  28. #endregion
  29. #region Constructor
  30. public DataGridPanel()
  31. {
  32. m_eventHelper = new XceedEventHelper( this );
  33. m_columnPanel = new ColumnPanel( this );
  34. this.Children.Add( new RootHost() );
  35. }
  36. #endregion
  37. #region RenderedColumns Internal Property
  38. internal IEnumerable<ColumnContainer> RenderedColumns
  39. {
  40. get
  41. {
  42. return this.ColumnPanel.RenderedColumns;
  43. }
  44. }
  45. #endregion
  46. #region AllColumns Internal Property
  47. internal IEnumerable<ColumnContainer> AllColumns
  48. {
  49. get
  50. {
  51. return this.ColumnPanel.AllColumns;
  52. }
  53. }
  54. #endregion
  55. #region ColumnPanel Internal Property
  56. internal ColumnPanel ColumnPanel
  57. {
  58. get
  59. {
  60. return m_columnPanel;
  61. }
  62. }
  63. #endregion
  64. #region EventManager Internal Property
  65. internal XceedEventHelper EventManager
  66. {
  67. [DebuggerStepThrough]
  68. get
  69. {
  70. return m_eventHelper;
  71. }
  72. }
  73. private readonly XceedEventHelper m_eventHelper;
  74. #endregion
  75. #region RootHost Internal Property
  76. internal RootHost RootHost
  77. {
  78. get
  79. {
  80. return ( RootHost )this.Children[ this.RootContainerIndex ];
  81. }
  82. }
  83. #endregion
  84. #region FixedHeaders Internal Property
  85. internal IEnumerable<UIElement> FixedHeaders
  86. {
  87. get
  88. {
  89. return CompatibilityUtils.GetEnumerable(this.Children)
  90. .Take( this.RootContainerIndex );
  91. }
  92. }
  93. #endregion
  94. #region FixedFooters Internal Property
  95. internal IEnumerable<UIElement> FixedFooters
  96. {
  97. get
  98. {
  99. return CompatibilityUtils.GetEnumerable(this.Children)
  100. .Skip( this.RootContainerIndex + 1 );
  101. }
  102. }
  103. #endregion
  104. #region RootContainerIndex Internal Property
  105. internal int RootContainerIndex
  106. {
  107. get
  108. {
  109. for(int i=0;i<this.Children.Count;i++)
  110. {
  111. if( this.Children[i] is RootHost )
  112. return i;
  113. }
  114. throw new DataGridInternalException();
  115. }
  116. }
  117. #endregion
  118. #region PendingTransitionContext Internal Property
  119. internal TransitionContext PendingTransitionContext
  120. {
  121. get;
  122. set;
  123. }
  124. #endregion
  125. #region ColumnElementHosts Internal Property
  126. internal IEnumerable<IColumnElementHost> ColumnElementHosts
  127. {
  128. get
  129. {
  130. ColumnElementHostExtractorVisitor visitor = new ColumnElementHostExtractorVisitor();
  131. this.Accept( visitor );
  132. // Do not return the visitor.Host collection. We want the returned IEnumerable
  133. // to be dynamic and recalculated on each enumration.
  134. foreach( IColumnElementHost host in visitor.Hosts )
  135. {
  136. yield return host;
  137. }
  138. }
  139. }
  140. #endregion
  141. #region ColumnPanelMeasureManager Private Property
  142. private IManageColumnsMeasure ColumnPanelMeasureManager
  143. {
  144. get
  145. {
  146. return ( IManageColumnsMeasure )this.GetElementOrParentBase<IManageColumnsMeasure>();
  147. }
  148. }
  149. #endregion
  150. #region UnconstrainedStateChanged Internal Event
  151. internal event EventHandler UnconstrainedStateChanged;
  152. private void OnUnconstrainedStateChanged()
  153. {
  154. if( this.UnconstrainedStateChanged != null )
  155. {
  156. this.UnconstrainedStateChanged( this, EventArgs.Empty );
  157. }
  158. }
  159. #endregion
  160. protected override Size MeasureOverride( Size availableSize )
  161. {
  162. bool isInDesign = DesignerProperties.GetIsInDesignMode();
  163. if( double.IsInfinity( availableSize.Width ) || double.IsNaN( availableSize.Width ) )
  164. {
  165. //If in an unconstrained environement and debugging
  166. if( !isInDesign && Debugger.IsAttached )
  167. {
  168. //Warn the developer the size of the grid has been arbitrary fixed.
  169. this.OnUnconstrainedStateChanged();
  170. }
  171. //Temporary value for design time purpose.
  172. availableSize.Width = 640d;
  173. }
  174. if( double.IsInfinity( availableSize.Height ) || double.IsNaN( availableSize.Height ) )
  175. {
  176. //If in an unconstrained environement and debugging
  177. if( !isInDesign && Debugger.IsAttached )
  178. {
  179. //Warn the developer the size of the grid has been arbitrary fixed.
  180. this.OnUnconstrainedStateChanged();
  181. }
  182. //Temporary value for design time purpose.
  183. availableSize.Height = 480d;
  184. }
  185. double columnPanelWidth = this.ColumnPanelMeasureManager.OnMeasureOverride( availableSize ).Width;
  186. //Invalidate the measure of all the column element hosts in order
  187. //to have the cells not clipped when the ColumnWidth changes.
  188. this.InvalidateColumnHostsMeasure();
  189. Size measuredSize = new Size( Math.Min( columnPanelWidth, availableSize.Width) , 0 );
  190. int rootContainerIndex = this.RootContainerIndex;
  191. Action<int> measureChild = (i) =>
  192. {
  193. UIElement child = this.Children[ i ];
  194. child.Measure( availableSize );
  195. availableSize.Height = Math.Max( 0d, availableSize.Height - child.DesiredSize.Height );
  196. measuredSize.Height += child.DesiredSize.Height;
  197. };
  198. //Measure FixedHeaders
  199. for( int i = 0; i < rootContainerIndex; i++ )
  200. {
  201. measureChild( i );
  202. }
  203. //Measure FixedFooters
  204. for( int i = rootContainerIndex+1; i < this.Children.Count; i++ )
  205. {
  206. measureChild( i );
  207. }
  208. RootHost rootContainer = ( RootHost )this.Children[ rootContainerIndex ];
  209. //Measure the RootContainer
  210. rootContainer.Measure( availableSize );
  211. Size containerSize = rootContainer.DesiredSize;
  212. measuredSize.Height += Math.Min( availableSize.Height, containerSize.Height );
  213. return measuredSize;
  214. }
  215. protected override Size ArrangeOverride( Size finalSize )
  216. {
  217. int rootContainerIndex = this.RootContainerIndex;
  218. m_columnPanel.Arrange( finalSize, new LayoutParameters( this.PendingTransitionContext ) );
  219. this.PendingTransitionContext = null;
  220. //Invalidte the arrange of all the column elements hosts in order
  221. //to have the cells layouted
  222. this.InvalidateColumnHostsArrange();
  223. double headersArrangeHeight = 0;
  224. double footersArrangeHeight = 0;
  225. Rect finalRect = new Rect( new Point( 0, 0 ), finalSize );
  226. for( int i = 0; i < rootContainerIndex; i++ )
  227. {
  228. UIElement child = this.Children[ i ];
  229. finalRect.Height = child.DesiredSize.Height;
  230. child.Arrange( finalRect );
  231. finalRect.Y += finalRect.Height;
  232. headersArrangeHeight += finalRect.Height;
  233. }
  234. finalRect = new Rect( new Point( 0, finalSize.Height ), finalSize );
  235. for( int i = this.Children.Count - 1; i > rootContainerIndex; i-- )
  236. {
  237. UIElement child = this.Children[ i ];
  238. finalRect.Height = child.DesiredSize.Height;
  239. finalRect.Y -= finalRect.Height;
  240. child.Arrange( finalRect );
  241. footersArrangeHeight += finalRect.Height;
  242. }
  243. finalRect = new Rect( 0,
  244. headersArrangeHeight,
  245. finalSize.Width,
  246. Math.Max( 0d, finalSize.Height - headersArrangeHeight - footersArrangeHeight ) );
  247. this.Children[rootContainerIndex].Arrange( finalRect );
  248. return finalSize;
  249. }
  250. internal void Accept( IVisitor visitor )
  251. {
  252. visitor.Visit( this );
  253. }
  254. internal void EndTransition()
  255. {
  256. this.ColumnPanel.EndTransition();
  257. this.InvalidateColumnHostsArrange();
  258. }
  259. internal void SetHeadersFooters( IList<UIElement> headers, IList<UIElement> footers )
  260. {
  261. //Remove all but the RootContainer
  262. int rootContainerIndex = this.RootContainerIndex;
  263. int headersCount = this.RootContainerIndex;
  264. int footersCount = this.Children.Count - this.RootContainerIndex - 1;
  265. bool updateHeaders = !this.FixedHeaders.SequenceEqual(headers);
  266. bool updateFooters = !this.FixedFooters.SequenceEqual(footers);
  267. if(updateHeaders)
  268. {
  269. //Remove current headers
  270. for(int i=0;i<headersCount;i++)
  271. {
  272. this.Children.RemoveAt(0);
  273. }
  274. headersCount = 0;
  275. }
  276. if(updateFooters)
  277. {
  278. //Remove current footers
  279. for( int i = 0; i < footersCount; i++ )
  280. {
  281. this.Children.RemoveAt(headersCount + 1);
  282. }
  283. }
  284. if(updateHeaders)
  285. {
  286. for(int i=0;i<headers.Count;i++)
  287. {
  288. this.Children.Insert(i,headers[i]);
  289. }
  290. }
  291. if(updateFooters)
  292. {
  293. for(int i=0;i<footers.Count;i++)
  294. {
  295. this.Children.Add(footers[i]);
  296. }
  297. }
  298. }
  299. private void InvalidateColumnHostsMeasure()
  300. {
  301. foreach( IColumnElementHost host in this.ColumnElementHosts )
  302. {
  303. host.InvalidateColumnMeasure();
  304. }
  305. }
  306. private void InvalidateColumnHostsArrange()
  307. {
  308. foreach( IColumnElementHost host in this.ColumnElementHosts )
  309. {
  310. host.InvalidateColumnArrange();
  311. }
  312. }
  313. #region IVisitorElement Members
  314. void IVisitorElement.Accept( IVisitor visitor )
  315. {
  316. this.Accept( visitor );
  317. }
  318. #endregion
  319. #region IColumnPanelOwner Members
  320. void IColumnPanelOwner.OnColumnAdded( ColumnContainer added )
  321. {
  322. this.EventManager.RaiseEvent( DataGridPanel.ColumnAdded, new ColumnContainerEventArgs( this, added ) );
  323. }
  324. void IColumnPanelOwner.OnColumnRemoved( ColumnContainer removed )
  325. {
  326. this.EventManager.RaiseEvent( DataGridPanel.ColumnRemoved, new ColumnContainerEventArgs( this, removed ) );
  327. }
  328. void IColumnPanelOwner.InvalidatePanelMeasure()
  329. {
  330. this.InvalidateMeasure();
  331. }
  332. void IColumnPanelOwner.InvalidatePanelArrange()
  333. {
  334. this.InvalidateArrange();
  335. }
  336. #endregion
  337. #region IXceedRoutedEventElement Members
  338. XceedEventHelper IXceedRoutedEventElement.EventManager
  339. {
  340. [DebuggerStepThrough]
  341. get
  342. {
  343. return this.EventManager;
  344. }
  345. }
  346. #endregion
  347. #region Private Fields
  348. private readonly ColumnPanel m_columnPanel;
  349. #endregion
  350. }
  351. }