public virtual void DeleteItems(IndexPath[] indexPaths)
        {
            if (Busy)
            {
                string errorMessage = "Async loading not finished yet";
                if (Debug.isDebugBuild)
                {
                    throw new InvalidOperationException(errorMessage);
                }
                else
                {
                    Mvx.Error(errorMessage);
                    return;
                }
            }

            for (int i = 0; i < indexPaths.Length; ++i)
            {
                if (AllowSelection)
                {
                    if (_childList[indexPaths[i].Index] != null)
                    {
                        UIEventListener.Get(_childList[indexPaths[i].Index]).onClick -= ItemSelected;
                    }
                }

#if SPAWN_POOL		
				if ( usePool && _spawnPool != null )
					_spawnPool.Despawn(_childList[indexPaths[i].Index].transform, _spawnPool.transform);
				else
#endif
                _childList[indexPaths[i].Index].transform.parent = null;
                GameObject.Destroy(_childList[indexPaths[i].Index]);

                _childList.RemoveRange(indexPaths[i].Index, 1);
            }
			
			if ( Grid != null )
			{
				Grid.Reposition();	
			}
        }
        public virtual GameObject DequeueReusableCell(string reuseIdentifier, IndexPath indexPath)
        {
            if (reuseIdentifier != null)
            {
                this.Template = Templates[reuseIdentifier];
            }
            //Debug.Log( "DequeueReusableCell " + reuseIdentifier + "," + indexPath );
            GameObject parent = Grid != null ? Grid.gameObject : this.gameObject;

            GameObject cell = null;
#if !MVX_DBG
            //if (_childList.Count > indexPath.Index && _childList[indexPath.Index] != null)
            //{
            //    cell = _childList[indexPath.Index] as GameObject;
            //}
#endif
            if (cell == null)
            {
#if SPAWN_POOL			
				if ( usePool && _spawnPool != null )
					cell = _spawnPool.Spawn(this.Template.name).gameObject;
				else
#endif
                cell = GameObject.Instantiate(this.Template) as GameObject;

                _childList.Add(cell);

                if (cell != null && parent != null)
                {
                    Transform t = cell.transform;
                    t.parent = parent.transform;
                    t.localPosition = Vector3.zero;
                    t.localRotation = Quaternion.identity;
                    t.localScale = Vector3.one;
                }

            }

            return cell;
        }
        protected virtual IEnumerator GetInsertItemsEnumerator(IndexPath[] indexPaths)
        {
            for (int i = 0; i < indexPaths.Length; ++i)
            {
//				Debug.Log( string.Format("{0}%{1}={2},{0}/{1}={3}", i, AsyncPageSize, i % AsyncPageSize, i / AsyncPageSize ));
				
                if (!AsyncPaging || (AsyncPaging && ( i % AsyncPageSize == 0 && i / AsyncPageSize > 0 )) )
                {
//					yield return new ContinueAfterSeconds(1f);
//                  yield return new WaitForEndOfFrame();
//                  yield return new WaitForSeconds(1f);
	                yield return null; //Wait one Frame
                }

                GameObject cell = Source.GetCell(this, indexPaths[i]);

                if (cell != null)
                {
					Reposition(cell);
					
                    cell.name = string.Format("{0:000}", indexPaths[i].Index);

                    Progress = (float)i / (float)(indexPaths.Length - 1);
                    if (Progressed != null)
                    {
                        Progressed(this, new MvxValueEventArgs<GameObject>(cell));
                    }

                    if (AllowSelection)
                    {
                        UIEventListener.Get(cell).onClick += ItemSelected;
                    }
                }
            }
			
			Progress = 1f;
            Busy = false;
            
            if (Completed != null)
            {
                Completed(this, EventArgs.Empty);
            }
        }
		public void InsertItems(IndexPath[] indexPaths)
		{
			var iter = GetInsertItemsEnumerator(indexPaths);

			if ( AsyncLoad )
			{
            	StartCoroutine(iter);
			}
			else
			{
				while ( iter.MoveNext() ) ;
			}
		}
 //If the specified elements are visible, the UICollectionView will discard and then redisplay them.
 public virtual void ReloadItems(IndexPath[] indexPaths)
 {
     throw new NotImplementedException();
 }
 public virtual void SelectItem(IndexPath indexPath, bool animated, Vector2 scrollPosition)
 {
     throw new NotImplementedException();
 }
 public virtual void ItemSelected(UICollectionView collectionView, IndexPath indexPath)
 {
     // nothing to do in this base class
 }
 protected virtual GameObject GetOrCreateCellFor(UICollectionView collectionView, IndexPath indexPath,
                                                           object item)
 {
     return (GameObject)collectionView.DequeueReusableCell(DefaultCellIdentifier, indexPath);
 }
 protected abstract object GetItemAt(IndexPath indexPath);
        public virtual void InsertItems(IndexPath[] indexPaths)
        {
            if ( !_collectionView.Busy )
			{
				_collectionView.Progress = 0.0f;
				_collectionView.InsertItems(indexPaths);
			}
        }
 public virtual void DeleteItems(IndexPath[] indexPaths)
 {
     _collectionView.DeleteItems(indexPaths);
 }
        public override GameObject GetCell(UICollectionView collectionView, IndexPath indexPath)
        {
			if ( collectionView == null ) return null;
				
            var item = GetItemAt(indexPath);
            var cell = GetOrCreateCellFor(collectionView, indexPath, item);

            var bindable = cell.GetComponent(typeof(IMvxDataConsumer)) as IMvxDataConsumer;
            if (bindable != null)
            {
                bindable.DataContext = item;
            }
            return cell;
        }
        protected override object GetItemAt(IndexPath indexPath)
        {
            if (ItemsSource == null)
                return null;
#if MVX_DBG
            UnityEngine.Debug.LogError("MvxCollection view getting element!!!:" + indexPath.Index + ":" + indexPath.Row);
            UnityEngine.Debug.LogError("Item source type:"+ItemsSource);
#endif
            return ItemsSource.ElementAt(indexPath.Row);
        }
        private void CollectionChangedOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            //Debug.Log( "OnCollectionChanged " + e.Action );
            switch (e.Action)
            {
                case NotifyCollectionChangedAction.Reset:
                    Mvx.TaggedTrace(GetType().Name, "CollectionChangedOnCollectionChanged(Reset)");
                    ReloadData();
                    break;
                case NotifyCollectionChangedAction.Add:
                    {
                        Mvx.TaggedTrace(GetType().Name, "CollectionChangedOnCollectionChanged(Add)");
                        int startingIndex = e.NewStartingIndex;
                        int count = e.NewItems.Count;

                        IndexPath[] indexPaths = new IndexPath[count];

                        for (int i = 0, k = startingIndex; i < count; ++i, ++k)
                        {
                            indexPaths[i] = new IndexPath() { Index = k, Row = k };
                        }

                        InsertItems(indexPaths);

                        break;
                    }
                case NotifyCollectionChangedAction.Remove:
                    {
                        Mvx.TaggedTrace(GetType().Name, "CollectionChangedOnCollectionChanged(Remove)");
                        int startingIndex = e.OldStartingIndex;
                        int count = e.OldItems.Count;

                        IndexPath[] indexPaths = new IndexPath[count];

                        for (int i = 0, k = startingIndex; i < count; ++i, ++k)
                        {
                            indexPaths[i] = new IndexPath() { Index = k, Row = k };
                        }
                        DeleteItems(indexPaths);

                        break;
                    }
                case NotifyCollectionChangedAction.Replace:
                    {
                        throw new NotSupportedException("Replace is not supported");
                        //int startingIndex = e.NewStartingIndex;
                        //int count = e.NewItems.Count;
                        //for (int i = 0, k = startingIndex; i < count; ++i, ++k)
                        //{
                        //    GameObject.Destroy(_childList[k]);
                        //    var cell = GetOrCreateCellFor(_collectionView, "", e.NewItems[i]);
                        //    _childList[k] = cell;
                        //}
                        //RenameCell(startingIndex, startingIndex + count);
                        //Reposition();
                        //break;
                    }

                case NotifyCollectionChangedAction.Move:
                    {
                        throw new NotSupportedException("Move is not supported");
                        //int newStartingIndex = e.NewStartingIndex;
                        //int oldStartingIndex = e.OldStartingIndex;
                        //int count = e.OldItems.Count;
                        //var children = _childList.GetRange(oldStartingIndex, count);
                        //_childList.RemoveRange(oldStartingIndex, count);
                        //_childList.InsertRange(newStartingIndex, children);
                        //RenameCell(Math.Min(oldStartingIndex, newStartingIndex), Math.Max(oldStartingIndex, newStartingIndex) + count);
                        //Reposition();
                        //break;
                    }

            }

        }
 public virtual void MoveItem(IndexPath indexPath, IndexPath newIndexPath)
 {
     throw new NotImplementedException();
 }
        public override void ItemSelected(UICollectionView collectionView, IndexPath indexPath)
        {
            var item = GetItemAt(indexPath);

            var command = SelectionChangedCommand;
            if (command != null)
                command.Execute(item);

            SelectedItem = item;
        }
 public virtual GameObject CellForItem(IndexPath indexPath)
 {
     return _childList.ElementAt(indexPath.Index) as GameObject;
 }
        //UICollectionView will discard any visible items and then redisplay them
        public virtual void ReloadData()
        {
            StopAllCoroutines();
			
			x = 0;
			y = 0;
#if SPAWN_POOL
			if ( usePool && _spawnPool != null )
			{
				foreach (var child in _childList)
				{
					_spawnPool.Despawn(child.transform, _spawnPool.transform);
				}
			}
			else
			{
				foreach (var child in _childList)
            	{
               		GameObject.Destroy(child);
				}
			}
#else
            foreach (var child in _childList)
            {
                child.transform.parent = null;
                GameObject.Destroy(child);
            }
#endif
            _childList.Clear();

            if (Source != null)
            {
                int itemCount = Source.GetItemsCount(this, 0);

                if (itemCount > 0)
                {
                    IndexPath[] indexPaths = new IndexPath[itemCount];

                    for (int i = 0; i < indexPaths.Length; ++i)
                    {
                        indexPaths[i] = new IndexPath() { Index = i, Row = i };
                    }

                    Busy = true;
                    Progress = 0.0f;
					
					InsertItems(indexPaths);
                }
            }

        }
 public virtual void DeselectItem(IndexPath indexPath, bool animated)
 {
     throw new NotImplementedException();
 }
 public virtual GameObject GetCell(UICollectionView collectionView, IndexPath indexPath)
 {
     return new GameObject();
 }