快速入门:拖动内容

你可以在 GridViewListView 中拖动文本、图像或其他数据以对它们重新排序,也可以将这些项目拖到其他种类的控件上。

在 Windows 应用商店应用中,可以在 GridViewListView 中使用鼠标、触控笔势或语音拖动项目以对它们重新排序,也可以将项目从单个 GridViewListView 拖动到另一个 XAML 控件。若要从 GridViewListView 拖动,请将 CanDragItems 属性设置为 True。若要允许控件接受所拖动的项目,请将 AllowDrop 属性设置为 True

你可以向拖动操作应用动画。可以遵循拖放动画指南主题中提供的通用指南,尽管该主题是针对 JavaScript 而编写,但也同样适用。创建 UI 动画一文介绍了如何在 XAML 中应用拖动动画。

不支持在不同应用之间进行拖动,但是你可以使用共享 API 或剪贴板在不同应用之间传输数据。所有的数据传输 API 都共用一些类型(包括 Windows::ApplicationModel::DataTransfer ::DataPackage 类和 Windows::ApplicationModel::DataTransfer ::StandardDataFormats 枚举)。在拖动操作中,DataPackage 类用于包装要传输的数据,StandardDataFormats 枚举定义 DataPackage 为其提供特殊 Set* 方法的格式。这些格式包括文本、位图、HTML、RTF、URI 和 StorageItem 对象集合。DataPackageView 类提供异步 Get* 方法,在 Drop 事件处理程序中可以使用这些方法来检索数据。你还可以使用 DataPackage::SetData 方法和 DataPackageView::GetDataAsync 方法来拖动用户定义的对象。

允许在 GridView 或 ListView 中拖动项目

允许在 GridViewListView 中拖动项目非常简单,只需在 XAML 中为控件设置下列属性即可: AllowDrop="True" CanDragItems="True" CanReorderItems="True"

拖动基本步骤

无论要传输的是哪种数据,控件之间的拖动操作都涉及两个基本步骤:

  1. 在拖动手势开始的源(可以是 Windows::UI::Xaml::Controls::GridViewWindows::UI::Xaml::Controls::ListView)中处理 Windows::UI::Xaml::Controls::DragItemsStarting 事件。DragItemsStartingEventArgs 参数包含一个对正拖动的项目的引用。该参数还包含一个 Data 属性,该属性是将要传递到 拖放目标的 DataPackage。在事件处理程序中,从 DragItemsStartingEventArgs::Items 集合获取要传递的数据,然后使用该数据,按照适合所用方案的方式填充 Data 属性。

  2. 在拖放目标中处理 Windows::UI::Xaml::Controls::Drop 事件。检索所传入的 DataPackage 对象,调用 GetView 以获取它的 DataPackageView 属性,使用它的 Get* 方法来访问以前存储在 DragItemsStarting 事件中的数据。拖放目标可以是支持“放置”事件的任何 XAML 控件。

其他事件(DragEnterDragLeaveDragOver)主要用于创建动画或其他直观效果,但对于基本的数据传输操作本身不是必需的。

拖动文本的步骤

在以下示例中,假定拖放源是包含 String 项目的 GridView,DragItemsStarting_1 是 GridView 所触发的 DragItemsStarting 事件的事件处理程序。如果 GridView:: SelectionMode 属性设置为 Multiple,则 Items 集合可以包含多个元素。在以下示例中,假定 SelectionMode 设置为 Single,以便可以安全地假定要拖动的项目处于位置 0 处。

拖动:


void DragDrop::DragText::DragTextGridView_DragItemsStarting_1(Platform::Object^ sender, Windows::UI::Xaml::Controls::DragItemsStartingEventArgs^ e)
{    
    auto mytxt = safe_cast<String^>(e->Items->GetAt(0));
    e->Data->SetText(mytxt);
}

放置:

以下示例显示如何处理 Drop 事件。在本例中,假定拖放目标是一个 XAMLTextBlock 元素。


void DragDrop::DragText::DropTextHere_Drop_1(Platform::Object^ sender, Windows::UI::Xaml::DragEventArgs^ e)
{
    using namespace concurrency;
    using namespace Windows::ApplicationModel::DataTransfer;

    DataPackageView^ dataView = e->Data->GetView();
    create_task(dataView->GetTextAsync())
    .then([this, sender](String^ txt)
    {
        TextBlock^ tb = safe_cast<TextBlock^>(sender);
        tb->Text = txt;
    });
}

拖动位图的步骤

如果 BitmapImage 是从一个文件获取的,则可以使用 DataPackage::SetStorageItemsDataPackageView::GetStorageItemsAsync 方法以 IStorageItem 形式拖动它。而且,如果你必须为基于文件的可拖动 BitmapImage 对象创建 GridViewListView,则最佳方法是创建一个可绑定的包装对象,该对象中包含 BitmapImage(作为公共属性)和原始 StorageFile,或许还包括文件名或属性等其他信息。由于 IStorageItem 对象本身不可绑定,因此将它显示在 GridView 中不是十分容易。

要点  尽管可以使用 FileInformation 类将虚拟化文件对象绑定到 XAML 控件,但是拖动虚拟化对象却不是十分容易。

在以下示例中,假定拖动源是 ListView,它将数据绑定到用户定义的 PhotoWrapper 对象的列表。每个 PhotoWrapper 都包含一个 BitmapImageStorageFile 对象,后者是在最初打开文件时获取的。ListView 上的 DataTemplate 绑定到 ImageFile 属性。


    [Windows::UI::Xaml::Data::Bindable]
    public ref class PhotoWrapper sealed
    {
    public:
        property Windows::UI::Xaml::Media::Imaging::BitmapImage^ Thumbnail;
        property Windows::Storage::StorageFile^ ImageFile;
    };

拖动:

下面的 DragItemsStarting 事件处理程序显示如何在拖放操作中创建一个包含一个或多个 IStorageItem 对象的列表,以及如何将这些对象插入 DataPackage 中。


void DragDrop::DragImage::ListView_DragItemsStarting_1(Platform::Object^ sender, Windows::UI::Xaml::Controls::DragItemsStartingEventArgs^ e)
{
    IVector<IStorageItem^>^ selectedFiles = ref new Vector<IStorageItem^>();
    for (unsigned int i = 0; i < e->Items->Size; i++)
    {
        PhotoWrapper^ wrapper = safe_cast<PhotoWrapper^>(e->Items->GetAt(i));
        selectedFiles->Append(wrapper->ImageFile);
    }

    e->Data->SetStorageItems(selectedFiles);
}

放置:

在 Drop 事件中,获取只读 DataPackageView 属性,调用 OpenReadAsync 方法以检索数据流,然后从该数据流创建一个 BitmapImage。在拖放操作完成之后,为 Image 控件设置 Source 属性,然后从源列表中删除相应的 PhotoWrapper 对象。


void DragDrop::DragImage::ListView_Drop_1(Platform::Object^ sender, Windows::UI::Xaml::DragEventArgs^ e)
{
    DataPackageView^ dpView = e->Data->GetView();

    create_task(dpView->GetStorageItemsAsync())
    .then([this](IVectorView<IStorageItem^>^ images)
    {
        for (unsigned int i = 0; i < images->Size; i++)
        {
            create_task([images, i, this]()
            {
                // Get a stream from the file object.
                IStorageFile^ file = safe_cast<IStorageFile^>(images->GetAt(i));
                return file->OpenReadAsync();
            }).then([this](IRandomAccessStreamWithContentType^ s)
            {
                // Set the stream as the bitmap source
                BitmapImage^ bi = ref new BitmapImage();
                bi->SetSourceAsync(s);
                return bi;
            }).then([this](BitmapImage^ bi)
            {
                // Add the BitmapImage to the source list.
                // The update will be reflected in the ListView.
                m_targetImages->Append(bi);
            });
        }        
    });
}

拖动用户定义对象的步骤

可以通过将自定义对象插入到 DataPackage::Properties 关联容器中来拖动自定义对象。在这种情况下,由于 DataPackage 不了解要拖放的数据,因此你必须提供一个用来描述数据格式的字符串键。在拖动操作中,格式字符串对于你的应用是专用的字符串。因此,你不必选择全球通用的名称。只需提供在检索数据时所使用的相同字符串即可。 在该示例中,为所有的项目提供了相同的键,但是你还可以为每个项目提供一个不同的键。

在以下示例中,假定我们有一个可绑定的类 City,并且希望将一个或多个 City 对象从 GridView 拖动到 ListView


    [Windows::UI::Xaml::Data::Bindable]
    public ref class City sealed
    {
    public:
        City(Platform::String^ name, int pop)
        {
            this->Name = name;
            this->Population = pop;
        }
        property Platform::String^ Name;
        property int Population;
    };

拖动:


void DragDrop::MainPage::GridView_DragItemsStarting_1(Platform::Object^ sender, Windows::UI::Xaml::Controls::DragItemsStartingEventArgs^ e)
{
    for (auto item : e->Items)
    {    
        // If you want to drop only a subset of the dragged items,
        // then make each key unique.    
        e->Data->Properties->Insert("MyApp.MyCity", item);
    }
}

放置:

在 C++ 中的放置操作中,项目会从 DataPackage 检索,强制转换为其原始类型(即 City),而且会复制到拖放目标的数据源中。


void DragDrop::MainPage::ListViewDropTarget_Drop_1(Platform::Object^ sender, Windows::UI::Xaml::DragEventArgs^ e)
{    
    DataPackageView^ dpView = e->Data->GetView();
    for (auto prop : dpView->Properties)
    {
        auto city = safe_cast<City^>(prop->Value);
        m_dropTargetItems->Append(city);
    }  
}

 

 

显示:
© 2015 Microsoft