PageRenderTime 26ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/Xceed.Silverlight.Data/DataSourceGroupContext.cs

http://extendedsilverlight.codeplex.com
C# | 428 lines | 321 code | 90 blank | 17 comment | 32 complexity | 5de6b18f4b7925c171551ff570587322 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.Collections.ObjectModel;
  15. using System.ComponentModel;
  16. using System.Linq;
  17. using System.Windows.Data;
  18. namespace Xceed.Silverlight.Data
  19. {
  20. internal sealed class DataSourceGroupContext
  21. {
  22. #region Constructors
  23. internal DataSourceGroupContext( GroupHandler handler )
  24. : this(
  25. handler.GroupDescriptions,
  26. handler.GroupCollections,
  27. handler.GroupHeadersFootersSelector,
  28. handler.GroupStatFunctionsSelector,
  29. handler.GroupCountPolicy,
  30. handler.IncludeGroupItems,
  31. handler.IncludeGroupItemsCount )
  32. {
  33. }
  34. private DataSourceGroupContext()
  35. {
  36. m_readOnlyGroupDescriptions = new ReadOnlyCollection<GroupDescription>( m_groupDescriptions );
  37. }
  38. private DataSourceGroupContext( DataSourceGroupContext copy )
  39. : this(
  40. copy.GroupDescriptions,
  41. copy.GroupCollections,
  42. copy.GroupHeadersFootersSelector,
  43. copy.GroupStatFunctionsSelector,
  44. copy.GroupCountPolicy,
  45. copy.IncludeGroupItems,
  46. copy.IncludeGroupItemsCount )
  47. {
  48. }
  49. private DataSourceGroupContext(
  50. IEnumerable<GroupDescription> groupDescriptions,
  51. IEnumerable<IGroupCollection> groupCollections,
  52. IGroupHeadersFootersSelector groupHeadersFootersSelector,
  53. IGroupStatFunctionsSelector groupStatFunctionsSelector,
  54. GroupCountPolicy groupCountPolicy,
  55. bool includeGroupItems,
  56. bool includeGroupItemsCount )
  57. : this()
  58. {
  59. if( groupDescriptions.Count() != groupCollections.Count() )
  60. throw new ArgumentException( "groupCollections" );
  61. m_groupDescriptions.AddRange( groupDescriptions );
  62. m_groupCollections = new GroupLevelCollection( DataSourceGroupContext.Copy( groupCollections ) );
  63. m_groupHeadersFootersSelector = groupHeadersFootersSelector;
  64. m_groupStatFunctionsSelector = groupStatFunctionsSelector;
  65. m_groupCountPolicy = groupCountPolicy;
  66. m_includeGroupItems = includeGroupItems;
  67. m_includeGroupItemsCount = includeGroupItemsCount;
  68. }
  69. #endregion
  70. #region GroupDescriptions Property
  71. internal IList<GroupDescription> GroupDescriptions
  72. {
  73. get
  74. {
  75. return m_readOnlyGroupDescriptions;
  76. }
  77. }
  78. private readonly List<GroupDescription> m_groupDescriptions = new List<GroupDescription>();
  79. private readonly ReadOnlyCollection<GroupDescription> m_readOnlyGroupDescriptions;
  80. #endregion
  81. #region GroupCollections Property
  82. internal GroupLevelCollection GroupCollections
  83. {
  84. get
  85. {
  86. return m_groupCollections;
  87. }
  88. }
  89. private readonly GroupLevelCollection m_groupCollections;
  90. #endregion
  91. #region GroupNames Property
  92. internal IEnumerable<string> GroupNames
  93. {
  94. get
  95. {
  96. return DataUtils.GetGroupNames( this.GroupDescriptions );
  97. }
  98. }
  99. #endregion
  100. #region GroupHeadersFootersSelector Property
  101. internal IGroupHeadersFootersSelector GroupHeadersFootersSelector
  102. {
  103. get
  104. {
  105. return m_groupHeadersFootersSelector;
  106. }
  107. }
  108. private readonly IGroupHeadersFootersSelector m_groupHeadersFootersSelector;
  109. #endregion
  110. #region GroupStatFunctionsSelector Property
  111. internal IGroupStatFunctionsSelector GroupStatFunctionsSelector
  112. {
  113. get
  114. {
  115. return m_groupStatFunctionsSelector;
  116. }
  117. }
  118. private readonly IGroupStatFunctionsSelector m_groupStatFunctionsSelector;
  119. #endregion
  120. #region GroupCountPolicy Property
  121. internal GroupCountPolicy GroupCountPolicy
  122. {
  123. get
  124. {
  125. return m_groupCountPolicy;
  126. }
  127. }
  128. private readonly GroupCountPolicy m_groupCountPolicy;
  129. #endregion
  130. #region IncludeGroupItems Property
  131. internal bool IncludeGroupItems
  132. {
  133. get
  134. {
  135. return m_includeGroupItems;
  136. }
  137. }
  138. private readonly bool m_includeGroupItems;
  139. #endregion
  140. #region IncludeGroupItemsCount Property
  141. internal bool IncludeGroupItemsCount
  142. {
  143. get
  144. {
  145. return m_includeGroupItemsCount;
  146. }
  147. }
  148. private readonly bool m_includeGroupItemsCount;
  149. #endregion
  150. #region AnyHeaderFooter Property
  151. internal bool AnyHeaderFooter
  152. {
  153. get
  154. {
  155. IGroupHeadersFootersSelector selector = this.GroupHeadersFootersSelector;
  156. if( selector != null )
  157. {
  158. ICollection<GroupDescription> groupDescriptions = this.GroupDescriptions;
  159. for( int i = 0; i < groupDescriptions.Count; i++ )
  160. {
  161. DataPath dataPath = new DataPath( Enumerable.Repeat( GroupDataItem.Any, i + 1 ).ToArray() );
  162. if( ( selector.HasHeaders( dataPath ) ) || ( selector.HasFooters( dataPath ) ) )
  163. return true;
  164. }
  165. }
  166. return false;
  167. }
  168. }
  169. #endregion
  170. #region AnyCollapsedGroup Property
  171. internal bool AnyCollapsedGroup
  172. {
  173. get
  174. {
  175. foreach( IGroupCollection collection in m_groupCollections )
  176. {
  177. if( collection.AnyCollapsedGroup.GetValueOrDefault( collection.IsCollapsedByDefault ) )
  178. return true;
  179. }
  180. return false;
  181. }
  182. }
  183. #endregion
  184. #region AnyGroup Property
  185. internal bool AnyGroup
  186. {
  187. get
  188. {
  189. return ( m_groupCollections.Count > 0 );
  190. }
  191. }
  192. #endregion
  193. public override int GetHashCode()
  194. {
  195. int hashCode = 11;
  196. hashCode += 17 * this.GroupDescriptions.Count;
  197. hashCode += 17 * DataSourceGroupContext.GetHashCode( this.GroupHeadersFootersSelector );
  198. hashCode += 17 * DataSourceGroupContext.GetHashCode( this.GroupStatFunctionsSelector );
  199. hashCode += 17 * this.GroupCountPolicy.GetHashCode();
  200. hashCode += 17 * this.IncludeGroupItems.GetHashCode();
  201. hashCode += 17 * this.IncludeGroupItemsCount.GetHashCode();
  202. return hashCode;
  203. }
  204. public override bool Equals( object obj )
  205. {
  206. if( object.ReferenceEquals( obj, this ) )
  207. return true;
  208. DataSourceGroupContext context = obj as DataSourceGroupContext;
  209. if( object.ReferenceEquals( context, null ) )
  210. return false;
  211. if( context.GetHashCode() != this.GetHashCode() )
  212. return false;
  213. return ( object.Equals( context.GroupHeadersFootersSelector, this.GroupHeadersFootersSelector ) )
  214. && ( object.Equals( context.GroupStatFunctionsSelector, this.GroupStatFunctionsSelector ) )
  215. && ( object.Equals( context.GroupCountPolicy, this.GroupCountPolicy ) )
  216. && ( object.Equals( context.IncludeGroupItems, this.IncludeGroupItems ) )
  217. && ( object.Equals( context.IncludeGroupItemsCount, this.IncludeGroupItemsCount ) )
  218. && ( context.GroupDescriptions.SequenceEqual( this.GroupDescriptions ) )
  219. && ( context.GroupCollections.SequenceEqual( this.GroupCollections ) );
  220. }
  221. internal DataSourceGroupContext Clone()
  222. {
  223. return new DataSourceGroupContext( this );
  224. }
  225. internal IAsyncEnumerator<DataPath> GetHeadersEnumerator( DataPath groupPath )
  226. {
  227. IAsyncEnumerator<object> childEnumerator = this.GetHeadersFootersEnumerator( groupPath, true );
  228. return this.ConvertEnumerator( groupPath, HeaderFooterType.Header, childEnumerator );
  229. }
  230. internal IAsyncEnumerator<DataPath> GetFootersEnumerator( DataPath groupPath )
  231. {
  232. IAsyncEnumerator<object> childEnumerator = this.GetHeadersFootersEnumerator( groupPath, false );
  233. return this.ConvertEnumerator( groupPath, HeaderFooterType.Footer, childEnumerator );
  234. }
  235. private static int GetHashCode( object obj )
  236. {
  237. if( object.ReferenceEquals( obj, null ) )
  238. return 0;
  239. return obj.GetHashCode();
  240. }
  241. private static IEnumerable<IGroupCollection> Copy( IEnumerable<IGroupCollection> source )
  242. {
  243. foreach( IGroupCollection collection in source )
  244. {
  245. GroupCollection gc = collection as GroupCollection;
  246. if( gc != null )
  247. {
  248. yield return gc.Clone().AsReadOnly();
  249. }
  250. else
  251. {
  252. gc = new GroupCollection();
  253. if( collection.IsCollapsedByDefault )
  254. {
  255. gc.CollapseAll();
  256. }
  257. else
  258. {
  259. gc.ExpandAll();
  260. }
  261. ICollection<DataPath> groupCollection = gc;
  262. foreach( DataPath path in collection )
  263. {
  264. groupCollection.Add( path );
  265. }
  266. yield return gc.AsReadOnly();
  267. }
  268. }
  269. }
  270. private IAsyncEnumerator<object> GetHeadersFootersEnumerator(
  271. DataPath groupPath,
  272. bool isHeader )
  273. {
  274. if( groupPath == null )
  275. throw new ArgumentNullException( "groupPath" );
  276. if( !( groupPath.LastChild is GroupDataItem ) )
  277. throw new ArgumentException( "path must refer to a group", "groupPath" );
  278. IEnumerable<object> headersFooters = null;
  279. IGroupHeadersFootersSelector selector = this.GroupHeadersFootersSelector;
  280. if( selector != null )
  281. {
  282. if( isHeader )
  283. {
  284. headersFooters = selector.GetHeaders( groupPath );
  285. }
  286. else
  287. {
  288. headersFooters = selector.GetFooters( groupPath );
  289. }
  290. }
  291. List<object> data;
  292. if( headersFooters != null )
  293. {
  294. data = headersFooters.ToList();
  295. }
  296. else
  297. {
  298. data = new List<object>( 0 );
  299. }
  300. return new SyncToAsyncEnumerator<object>(
  301. new LocalListEnumerator<object>( data ) );
  302. }
  303. private IAsyncEnumerator<DataPath> ConvertEnumerator( DataPath groupPath, HeaderFooterType headerType, IAsyncEnumerator<object> childEnumerator )
  304. {
  305. return new HeaderFooterEnumerator( childEnumerator, groupPath, headerType );
  306. }
  307. #region HeaderFooterEnumerator Nested Type
  308. private class HeaderFooterEnumerator : ConversionEnumerator<object, DataPath>
  309. {
  310. internal HeaderFooterEnumerator( IAsyncEnumerator childEnumerator, DataPath groupPath, HeaderFooterType headerType )
  311. : base( childEnumerator )
  312. {
  313. if( groupPath == null )
  314. throw new ArgumentNullException( "groupPath" );
  315. m_groupPath = groupPath;
  316. m_type = headerType;
  317. }
  318. protected override DataPath Convert( DataSourceContext context, object value )
  319. {
  320. return m_groupPath.CreateChildPath( new HeaderFooterDataItem( value, m_type ) );
  321. }
  322. protected override object ConvertBack( DataSourceContext context, DataPath value )
  323. {
  324. HeaderFooterDataItem dataItem = ( HeaderFooterDataItem )value.LastChild;
  325. return dataItem.Data;
  326. }
  327. private readonly DataPath m_groupPath;
  328. private readonly HeaderFooterType m_type;
  329. }
  330. #endregion
  331. }
  332. }