Guida introduttiva: Trascinamento di contenuto

Gli utenti possono trascinare testo, immagini o altri dati per riordinarli in un controllo GridView o ListView, oppure trascinare elementi in altri tipi di controlli.

In un'app di Windows Store puoi usare il mouse, movimenti tocco o la voce per trascinare gli elementi in modo da riordinarli in un controllo GridView o ListView, oppure trascinare un elemento da un singolo controllo GridView o ListView a un altro controllo XAML. Per trascinare un elemento da un controllo GridView o ListView, imposta l'attributo CanDragItems su True. Per consentire a un controllo di accettare gli elementi trascinati, devi impostare l'attributo AllowDrop su True.

Puoi applicare animazioni alle operazioni di trascinamento della selezione. A tale scopo, puoi seguire le stesse linee guida generali fornite in Linee guida per le animazioni delle azioni di trascinamento, anche se tale argomento si riferisce a JavaScript. L'articolo Animazione dell'interfaccia utente illustra come applicare animazioni alle operazioni di trascinamento in XAML.

Le operazioni di trascinamento tra app diverse non sono supportate, ma per trasferire dati in tali scenari puoi usare le API di condivisione o gli Appunti. Tutte le API di trasferimento dati presentano un elemento in comune, ovvero includono la classe Windows::ApplicationModel::DataTransfer ::DataPackage e l'enumerazione Windows::ApplicationModel::DataTransfer ::StandardDataFormats. In un'operazione di trascinamento, la classe DataPackage viene usata per il wrapping dei dati da trasferire e l'enumerazione StandardDataFormats definisce i formati per cui DataPackage fornisce metodi Set* speciali, che includono Text, Bitmap, Html, Rtf, Uri e le raccolte di oggetti StorageItem. La classe DataPackageView fornisce i metodi Get* asincroni utilizzabili nel gestore dell'evento Drop per recuperare i dati. È inoltre possibile utilizzare il metodo DataPackage::SetData e i metodi DataPackageView::GetDataAsync per trascinare oggetti definiti dall'utente.

Per abilitare il trascinamento di elementi in un controllo GridView o ListView

Abilitare il trascinamento di elementi in un controllo GridView o ListView è semplicissimo. Basta impostare questi attributi sul controllo nel codice XAML: AllowDrop="True" CanDragItems="True" CanReorderItems="True"

Passaggi di base delle operazioni di trascinamento

Indipendentemente dal tipo di dati da trasferire, un'operazione di trascinamento tra due controlli prevede due passaggi di base:

  1. Gestire l'evento Windows::UI::Xaml::Controls::DragItemsStarting nel controllo di origine da cui ha inizio il gesto, che può essere un controllo Windows::UI::Xaml::Controls::GridView o Windows::UI::Xaml::Controls::ListView. Il parametro DragItemsStartingEventArgs contiene un riferimento agli elementi da trascinare. Il parametro contiene anche una proprietà Data che indica l'oggetto DataPackage da passare alla destinazione di rilascio. Nel gestore dell'evento, devi recuperare i dati che desideri passare dall'insieme DragItemsStartingEventArgs::Items e quindi utilizzare tali dati per popolare la proprietà Dati nel modo più appropriato per lo scenario.

  2. L'evento Windows::UI::Xaml::Controls::Drop deve essere gestito nella destinazione di rilascio. Devi recuperare l'oggetto DataPackage passato, chiamare GetView per recuperarne la proprietà DataPackageView e utilizzarne i metodi Get* per accedere ai dati precedentemente archiviati nell'evento DragItemsStarting. La destinazione di rilascio può essere costituita da qualsiasi controllo XAML che supporta l'evento "Drop".

Gli eventi aggiuntivi DragEnter, DragLeave e DragOver sono utili soprattutto per la creazione di animazioni o di altri effetti visivi, ma non sono essenziali per l'operazione base di trasferimento dati in sé.

Per trascinare testo

Nell'esempio seguente, supponi che l'origine del trascinamento sia costituita da un controllo GridView contenente elementi String e che DragItemsStarting_1 sia il gestore dell'evento DragItemsStarting generato dal controllo GridView. Se la proprietà GridView:: SelectionMode è impostata su Multiple, l'insieme Items può contenere più di un elemento. In questo esempio, presupponi che la proprietà SelectionMode sia impostata su Single, in modo da avere la certezza che l'elemento da trascinare si trovi nella posizione 0.

Trascinamento:


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);
}

Rilascio:

Il seguente esempio mostra come gestire l'evento Drop. In questo caso, supponi che la destinazione di rilascio sia un elemento XAML TextBlock.


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;
    });
}

Per trascinare bitmap

Se recuperi un oggetto BitmapImage da un file, puoi usare i metodi DataPackage::SetStorageItems e DataPackageView::GetStorageItemsAsync per trascinarlo come oggetto IStorageItem. Inoltre, se devi creare un controllo GridView o ListView che include oggetti BitmapImage trascinabili basati su file, l'approccio ottimale consiste nel creare un oggetto wrapper di cui è possibile effettuare il binding contenente l'oggetto BitmapImage e l'oggetto StorageFile originale come proprietà pubbliche ed eventualmente altre informazioni come il nome o gli attributi del file. Poiché un oggetto IStorageItem non è associabile di per sé, non può essere visualizzato facilmente in un controllo GridView.

Importante  Anche se è possibile utilizzare la classe FileInformation per associare oggetti file virtualizzati a un controllo XAML, gli oggetti virtualizzati non possono essere trascinati facilmente.

Nell'esempio seguente, immagina che l'origine del trascinamento sia costituita da un controllo ListView associato ai dati di un elenco di oggetti PhotoWrapper definiti dall'utente. Ogni oggetto PhotoWrapper contiene un oggetto BitmapImage e l'oggetto StorageFile da cui è stato ottenuto dall'apertura iniziale del file. L'oggetto DataTemplate nel controllo ListView è associato alla proprietà 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;
    };

Trascinamento:

Il seguente gestore dell'evento DragItemsStarting mostra come creare un elenco di uno o più oggetti IStorageItem nell'operazione di trascinamento e inserirli nell'oggetto 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);
}

Rilascio:

Nell'evento Drop devi recuperare la proprietà di sola lettura DataPackageView e chiamare il metodo OpenReadAsync per recuperare il flusso, quindi creare un oggetto BitmapImage da quest'ultimo. Al termine dell'operazione, imposta le proprietà Source nel controllo Image e quindi rimuovi l'oggetto PhotoWrapper corrispondente dall'elenco di origine.


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);
            });
        }        
    });
}

Per trascinare oggetti definiti dall'utente

Puoi trascinare oggetti personalizzati inserendoli nel contenitore associativo DataPackage::Properties. In questo caso, dato che DataPackage non è a conoscenza dei dati, devi fornire una chiave di stringa che descriva il formato dei dati. In un'operazione di trascinamento la stringa di formato è un'informazione privata dell'app. Non è pertanto necessario scegliere un nome interpretabile universalmente. È sufficiente fornire la stessa stringa quando recuperi i dati. In questo esempio viene usata la stessa chiave per tutti gli elementi, ma potresti anche fornire una chiave specifica per ogni elemento.

Nell'esempio seguente supponi di avere la classe City di cui è possibile effettuare il binding e di voler trascinare uno o più oggetti City da un controllo GridView a un controllo 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;
    };

Trascinamento:


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);
    }
}

Rilascio:

Nell'operazione di rilascio in C++, gli elementi vengono recuperati da DataPackage, quindi ne viene eseguito di nuovo il cast al tipo originale City e poi vengono copiati nell'origine dati per la destinazione di rilascio.


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);
    }  
}

 

 

Mostra:
© 2015 Microsoft