GridView:获取Drop事件的索引

时间:2014-12-02 12:00:24

标签: xaml gridview windows-runtime windows-store-apps winrt-xaml

如何在GridViewItem的{​​{1}}事件中删除OnDrop 索引位置 ?正如我所读到的,GridView可以使用GridView.ItemContainerGenerator.ContainerFromItem(item) ItemContainerGenerator null

这是我目前的代码:

void gridMain_DragItemsStarting(object sender, DragItemsStartingEventArgs e)
{
    var item = e.Items.First();
    var source = sender;
    e.Data.Properties.Add("item", item);
    e.Data.Properties.Add("source", sender);
}

void gridMain_Drop(object sender, DragEventArgs e)
{
    var item = e.Data.Properties.Where(p => p.Key == "item").Single();

    object source;
    e.Data.Properties.TryGetValue("source", out source);
    var s = ((GridView)source).ItemContainerGenerator.ContainerFromItem(item);
}

任何提示或建议都会非常有用。

1 个答案:

答案 0 :(得分:2)

使用DragEventArgs的GetPosition方法查找项目被删除的位置,然后计算实际索引,请参阅下面的处理程序代码片段。使用此here作为答案(方案3),MSDN example提出了类似问题。

private void GridView_Drop(object sender, DragEventArgs e)
{
    GridView view = sender as GridView;

    // Get your data
    var item = e.Data.Properties.Where(p => p.Key == "item").Single();

    //Find the position where item will be dropped in the gridview
    Point pos = e.GetPosition(view.ItemsPanelRoot);

    //Get the size of one of the list items
    GridViewItem gvi = (GridViewItem)view.ContainerFromIndex(0);
    double itemHeight = gvi.ActualHeight + gvi.Margin.Top + gvi.Margin.Bottom;

    //Determine the index of the item from the item position (assumed all items are the same size)
    int index = Math.Min(view.Items.Count - 1, (int)(pos.Y / itemHeight));

    // Call your viewmodel with the index and your data.
}

编辑:请将此视为原型。我尝试了它并且它已正常工作,但您可以根据您的方案进行修改(调整延迟超时,立即区分更多TaskCompletionSource等)。

我们的想法是在删除操作后启动任务,以检查项目是仅被删除还是重新排序。

private async void observableCollection_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
    if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove)
    {
        object removedItem = e.OldItems[0];
        var reorderTask = NoticeReorderAsync(removedItem);
        try
        {
            var task = await Task.WhenAny(reorderTask, Task.Delay(100));

            if (reorderTask == task)
            {
                // removedItem was in fact reordered
                Debug.WriteLine("reordered");
            }
            else
            {
                TryCancelReorder();
                // removedItem was really removed
                Debug.WriteLine("removedItem");
            }
        }
        catch (TaskCanceledException ex)
        {
            Debug.WriteLine("removedItem (from exception)");
        }
        finally
        {
            tcs = null;
        }
    }
    else if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
    {
        object addedItem = e.NewItems[0];
        bool added = NoticeAdd(addedItem);
        if (added)
        {
            // addedItem was just added, not reordered
            Debug.WriteLine("added");
        }
    }

}

TaskCompletionSource<object> tcs;

private void TryCancelReorder()
{
    if (tcs != null)
    {
        tcs.TrySetCanceled();
        tcs = null;
    }
}

private Task NoticeReorderAsync(object removed)
{
    TryCancelReorder();
    tcs = new TaskCompletionSource<object>(removed);

    return tcs.Task;
}

private bool NoticeAdd(object added)
{
    if (tcs != null)
    {
        try
        {
            if (object.Equals(tcs.Task.AsyncState, added))
            {
                tcs.TrySetResult(added);
                return false;
            }
            else
            {
                tcs.TrySetCanceled();
                return true;
            }
        }
        finally
        {
            tcs = null;
        }
    }
    return true;
}