/// <summary>
        /// If the selection in the combo-box for the group-selection changes,
        /// the grouped grid view scrolls the selected group into view. This is
        /// especially useful in narrow views.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The event arguments.
        /// </param>
        private void GroupComboBoxSelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            string key = GroupComboBox.SelectedItem as string;
            GroupInfoCollection <Item> group = _source.Single(groupInfoList => groupInfoList.Key == key);

            ItemsByCategory.ScrollIntoView(group);
        }
        /// <summary>
        /// If the data structure bound to the grid-view changes and causes the layout to update
        /// (i.e. if an item was added), it is scrolled to the category in the combo box.
        /// We can't call the scroll directly after adding the item (in AddItemClick), because
        /// we have to wait until the dependency property signals the control that it changed and
        /// the control changed its layout. If a new column is added by adding the new item, the control
        /// wouldn't scroll that new column into view otherwise.
        /// </summary>
        /// <param name="sender">The sender</param>
        /// <param name="e">The event arguments</param>
        private void ItemsByCategoryLayoutUpdated(object sender, object e)
        {
            int needsToScroll = Interlocked.Exchange(ref _itemAdded, 0);

            if (needsToScroll != 0)
            {
                string key = GroupComboBox.SelectedItem as string;
                GroupInfoCollection <Item> group = _source.Single(groupInfoList => groupInfoList.Key == key);
                ItemsByCategory.ScrollIntoView(group);
            }
        }
        private async void DeleteItem(Item item)
        {
            var resp = await _dialogService.DisplayAlertAsync("", "Desea eliminar este item?", "Ok", "Cancelar");

            if (!resp || item == null)
            {
                return;
            }

            ItemsByCategory.Remove(item);
            Items.Remove(item);
            await _cache.InsertLocalObject(CacheKeyDictionary.ItemList, Items);
        }
        public async void DeleteCategory(Category cat)
        {
            if (cat == null)
            {
                return;
            }

            var resp = await _dialogService.DisplayAlertAsync("", "Desea eliminar esta categoria?", "Ok", "Cancelar");

            if (!resp)
            {
                return;
            }

            var categories = (Views.MasterPage.Current.BindingContext as MasterPageViewModel)?.MenuItems;

            if (!categories.Contains(cat))
            {
                return;
            }

            categories.Remove(cat);
            (Views.MasterPage.Current.BindingContext as MasterPageViewModel).MenuItems = categories;

            var items = Items.ToList();

            foreach (var item in items)
            {
                if (item.Category == cat.DisplayName)
                {
                    if (ItemsByCategory.Contains(item))
                    {
                        ItemsByCategory.Remove(item);
                    }

                    Items.Remove(item);
                }
            }

            ShowItemsByCategory(null, true);
            await _cache.InsertLocalObject(CacheKeyDictionary.ItemList, Items);

            await _cache.InsertLocalObject(CacheKeyDictionary.CategoryItems, categories);
        }
        public void ShowItemsByCategory(Category categoryItem, bool showAll = false)
        {
            ItemsByCategory  = new ObservableCollection <Item>();
            _currentCategory = categoryItem;

            if (string.IsNullOrEmpty(categoryItem?.DisplayName) || showAll)
            {
                Title           = "Todas las tareas";
                ItemsByCategory = new ObservableCollection <Item>(Items);
                return;
            }

            foreach (var item in Items)
            {
                if (item.Category == categoryItem.DisplayName)
                {
                    ItemsByCategory.Add(item);
                }
            }

            Title = categoryItem.DisplayName;
        }
        public override async void OnNavigatedTo(NavigationParameters parameters)
        {
            if (parameters.ContainsKey("itemCreated"))
            {
                var itemSelected = (Item)parameters["itemCreated"];
                itemSelected.Id = (Items?.Count > 0)? Items.Last().Id + 1 : 1;
                Items.Add(itemSelected);

                if (_currentCategory == null)
                {
                    ItemsByCategory.Add(itemSelected);
                }
                else if (itemSelected.Category == _currentCategory?.DisplayName)
                {
                    ItemsByCategory.Add(itemSelected);
                }

                if (itemSelected.Date.Date == DateTime.Today.Date)
                {
                    ShowNotification(0, true);
                }

                await _cache.InsertLocalObject(CacheKeyDictionary.ItemList, Items);
            }

            if (parameters.ContainsKey("itemEdited"))
            {
                var newItem = (Item)parameters["itemEdited"];

                //by cat
                var iEdited    = ItemsByCategory.Single(i => i.Id == newItem.Id);
                var idxNewItem = ItemsByCategory.IndexOf(iEdited);

                ItemsByCategory.Remove(iEdited);
                ItemsByCategory = _itemsByCategory;

                if (_currentCategory == null)
                {
                    ItemsByCategory.Insert(idxNewItem, newItem);
                }
                else if (newItem.Category == _currentCategory.DisplayName)
                {
                    ItemsByCategory.Insert(idxNewItem, newItem);
                }

                //origin
                var itemEdited   = Items.Single(i => i.Id == newItem.Id);
                var indexNewItem = Items.IndexOf(itemEdited);

                Items.Remove(itemEdited);
                Items.Insert(indexNewItem, newItem);

                await _cache.InsertLocalObject(CacheKeyDictionary.ItemList, Items);
            }

            if (parameters.ContainsKey("itemCompleted"))
            {
                var newItem    = (Item)parameters["itemCompleted"];
                var itemEdited = Items.Single(i => i.Id == newItem.Id);
                itemEdited.Completed = true;

                await _cache.InsertLocalObject(CacheKeyDictionary.ItemList, Items);
            }
        }