Agosto de 2015
Volumen 30, número 8
Windows 10: característica moderna de arrastrar y colocar para aplicaciones universales de Windows
Por Alain Zanchetta
Este artículo se basa en la vista previa pública de Windows 10 y Visual Studio 2015.
Arrastrar y colocar es una manera intuitiva de transferir datos dentro de una aplicación o entre aplicaciones en el escritorio de Windows. Hizo su debut en Windows 3.1 con el Administrador de archivos y luego se extendió a todas las aplicaciones que admiten OLE 2, como Microsoft Office. Cuando se publicó Windows 8, Microsoft presentó un nuevo tipo de aplicación de Windows, denominada aplicación de la Tienda Windows, que se diseñó para tabletas y que siempre se mostraba en el modo de pantalla completa. Debido a que solo una aplicación estaba visible en un momento dado, arrastrar y colocar entre aplicaciones tenía sentido y se desarrollaron otras formas de compartir datos, como acceso a Compartir. Sin embargo, Windows 10, las aplicaciones en un PC de escritorio se están ejecutando una vez en modo de ventana, lo que significa que se muestran varias ventanas en la pantalla, y por lo tanto, arrastrar y colocar regresa como una API de aplicación universal de Windows, con la adición de nuevas características que mejoran la experiencia de usuario.
Conceptos de arrastrar y colocar
Arrastrar y colocar permite al usuario transferir datos entre aplicaciones o dentro de una aplicación con un gesto estándar (mantener presionado y mover con el dedo o presionar y mover con un mouse o lápiz).
El origen del arrastre, que es el área o la aplicación donde se desencadena el gesto del arrastre, proporciona los datos que se van a transferir al rellenar un objeto de paquete de datos que puede contener formatos de datos estándar, incluidos texto, RTF, HTML, mapas de bits, elementos de almacenamiento o formatos de datos personalizados. El origen también indica el tipo de operaciones que admite: copiar, mover o vincular. Cuando se libera el puntero, se produce la colocación. El destino de la colocación, que es la aplicación o el área que se encuentra debajo del puntero, procesa el paquete de datos y devuelve el tipo de operación que ha realizado.
Durante la operación de arrastrar y colocar, la interfaz de usuario de arrastre ofrece una indicación visual del tipo de operación de arrastrar y colocar que está teniendo lugar. Esta información visual se ofrece inicialmente por el origen, pero puede cambiarse por los destinos conforme el puntero se mueve sobre ellos.
La característica moderna de arrastrar y colocar está disponible en escritorio, tableta y teléfono. Permite la transferencia de datos entre cualquier tipo de aplicación o dentro de ella, incluidas las aplicaciones de Windows clásico, aunque en este artículo se centra en la API de XAML para la característica moderna de arrastrar y colocar.
Implementación de arrastrar y colocar
El origen de arrastre y el destino de colocación desempeñan roles diferentes. Una aplicación puede tener componentes de interfaz de usuario que son solo orígenes de arrastre, solo destinos para colocación o ambos, como la aplicación Photo Booth de ejemplo que se muestra en la Figura 1.
Figura 1 Arrastrar orígenes y colocar destinos
Una operación de arrastrar y colocar se controla por completo mediante la intervención del usuario, por lo que su implementación se basa casi exclusivamente en eventos, como se muestra en la Figura 2.
Figura 2 Arrastrar y colocar eventos
Implementar un origen de arrastre En Windows 8.1, una ListView puede ser el origen de una operación de arrastrar y colocar en la aplicación si su propiedad CanDragItems se establece en true:
<ListView CanDragItems="True"
DragItemsStarting="ListView_DragItemsStarting"
ItemsSource="{Binding Pictures}"
ItemTemplate="{StaticResource PictureTemplate}"
/>
La aplicación puede controlar el evento DragItemsStarting en el origen. Aún se admite en Windows 10 con la adición de un evento DragItemsCompleted, que no era necesario en las aplicaciones de Windows 8.1 donde el origen y el destino deben pertenecer al mismo proceso.
El origen de arrastre principal para la característica moderna de arrastrar y colocar es el UIElement, que ofrece acceso a todas las características modernas de arrastrar y colocar y es el enfoque principal de este artículo.
Es una manera de hacer que el UIElement sea arrastrable es establecer su propiedad CanDrag en true. Esto se puede realizar en el marcado o en el código subyacente. El marco de trabajo XAML controla el reconocimiento de gestos y desencadena el evento DragStarting para indicar el inicio de una operación de arrastre. La aplicación debe configurar el DataPackage rellenando su contenido e indicando qué operaciones se admiten. La aplicación de origen puede incluir diferentes formatos en el DataPackage, lo que hará que sea compatible con más destinos, como se muestra en la Figura 3. Las operaciones admitidas se definen en el tipo DataPackageOperation y pueden ser copiar, mover, vincular o cualquier combinación de estas.
Figura 3 Control de DragStarting y relleno de DataPackage
private void DropGrid_DragStarting(UIElement sender,
DragStartingEventArgs args)
{
if (Picture == null)
{
args.Cancel = true;
}
else if (_fileSource != null)
{
args.Data.RequestedOperation =
DataPackageOperation.Copy | DataPackageOperation.Move;
args.Data.SetStorageItems(new IStorageItem[] { _fileSource });
...
}
Puede cancelar la operación de arrastre en el controlador de eventos estableciendo la propiedad Cancel del parámetro DragStartingEventArgs; por ejemplo, en nuestra aplicación de ejemplo, un marcador de posición de la imagen iniciará una operación de arrastre solo si ha recibido una imagen o un archivo.
El controlador DragStartingEvent también es el lugar donde la aplicación de origen puede personalizar la interfaz de usuario de arrastre, que se explica más adelante en este artículo.
En algunos casos, es posible que la aplicación desee usar un gesto especial para iniciar una operación de arrastrar y colocar o bien, que desee permitir arrastrar un control cuyas interacciones normales interferirán con el gesto de arrastrar y colocar, por ejemplo, el TextBox, que ya reacciona ante eventos de puntero hacia abajo cambiando su selección. En estos casos, la aplicación puede implementar su propia detección de gestos y luego iniciar una operación de arrastrar y colocar llamando al método StartDragAsync. Tenga en cuenta que este método espera un identificador de puntero y, por lo tanto, no puede iniciar una operación de arrastrar y colocar con dispositivos no estándar, como un sensor de Kinect. Una vez que se llama a StartDragAsync, el resto de la operación de arrastrar y colocar sigue el mismo patrón como si se hubiese usado CanDrag=True, incluido el evento DragStarting.
Cuando el usuario ha liberado el puntero, se completa la operación de arrastrar y colocar y se notifica al origen a través del evento DropCompleted, que contiene la DataPackageOperation devuelta por el destino en la que el usuario liberó el puntero o DataPackageOperation.None si el puntero se liberó en un destino que no acepta los datos o si se ha presionado Cancelar:
private void DropGrid_DropCompleted(UIElement sender, DropCompletedEventArgs args)
{
if (args.DropResult == DataPackageOperation.Move)
{
// Move means that we should clear our own image
Picture = null;
_bitmapSource = null;
_fileSource = null;
}
}
StartDragAsync devuelve una IAsyncOperation<DataPackageOperation>; la aplicación de origen puede controlar el final de la operación esperando en la IAsyncOperation o controlando el evento DropCompleted. La cancelación mediante programación después del evento DragStarting es posible a través de la interfaz de IAsyncOperation, pero podría ser molesta para el usuario.
Tenga en cuenta que aunque tanto la operación de arrastrar y colocar de ListView como la de UIElement se implementan en los mismos servicios de sistema y son totalmente compatibles, no generan los mismos eventos en el lado del origen. Es decir, si una ListView tiene su propiedad CanDragItems establecida en true, solo se generan DragItemsStarting y DragItemsCompleted. DragStarting y DropCompleted son eventos relacionados con la propiedad CanDrag de UIElement.
Implementar un destino de colocación Cualquier UIElement Any puede ser un destino de colocación siempre que su propiedad AllowDrop se establezca en true. Durante una operación de arrastrar y colocar, se pueden generar los siguientes eventos en un destino: DragEnter, DragOver, DragLeave y Drop. Estos eventos ya existen en Windows 8.1, pero se ha ampliado la clase DragEventArgs en Windows 10 para dar acceso a las aplicaciones para todas las características de la moderna función arrastrar y colocar. Al controlar un evento de arrastrar y colocar, la aplicación de destino en primer lugar debe inspeccionar el contenido del DataPackage a través de la propiedad DataView del argumento del evento; en la mayoría de los casos, comprobar la presencia de un tipo de dato es suficiente y se puede realizar de forma sincrónica. En algunos casos, como con archivos, la aplicación podría tener que comprobar el tipo de los archivos disponibles antes de aceptar o ignorar el DataPackage. Esta es una operación asincrónica y requiere que la aplicación de destino tome un aplazamiento y la complete más tarde (este patrón se detalla más adelante en este artículo).
Cuando el destino ha determinado si puede procesar los datos, debe establecer la propiedad AcceptedOperation de la instancia de DragEventArgs para permitir que el sistema ofrezca los comentarios adecuados al usuario.
Tenga en cuenta que si la aplicación devuelve DataTransferOperation.None (o una operación no aceptada por el origen) desde un controlador de eventos, la colocación no tendrá lugar incluso si el usuario libera el puntero sobre el destino; en su lugar, se generará el evento DragLeave.
La aplicación puede controlar DragEnter o DragOver; la AcceptedOperation devuelta por DragEnter se conserva si no se controla DragOver. Como a DragEnter solo se la llama una vez, debe preferirse a DragOver por motivos de rendimiento. Sin embargo, en el caso de los destinos anidados, es necesario devolver el valor correcto de DragOver en el caso de que un objetivo primario puede invalidarlo (la configuración de Handled en true impide que el evento aparezca en el elemento primario). En la aplicación de ejemplo, cada marcador de posición de foto busca imágenes en el DataPackage y enruta el evento a la cuadrícula principal únicamente si no hay ninguna imagen disponible, lo que permite a la cuadrícula aceptar el texto incluso si se coloca físicamente en un marcador de posición (vea la Figura 4).
Figure 4 Controlar DragEnter e inspeccionar DataPackage
private async void DropGrid_DragEnter(object sender, DragEventArgs e)
{
if (!App.IsSource(e.DataView))
{
bool forceMove = ((e.Modifiers & DragDropModifiers.Shift) ==
DragDropModifiers.Shift);
if (e.DataView.Contains(StandardDataFormats.Bitmap))
{
_acceptData = true;
e.AcceptedOperation = (forceMove ? DataPackageOperation.Move :
DataPackageOperation.Copy);
e.DragUIOverride.Caption = "Drop the image to show it in this area";
e.Handled = true;
}
else if (e.DataView.Contains(StandardDataFormats.StorageItems))
{
// Notify XAML that the end of DropGrid_Enter does
// not mean that we have finished to handle the event
var def = e.GetDeferral();
_acceptData = false;
e.AcceptedOperation = DataPackageOperation.None;
var items = await e.DataView.GetStorageItemsAsync();
foreach (var item in items)
{
try
{
StorageFile file = item as StorageFile;
if ((file != null) && file.ContentType.StartsWith("image/"))
{
_acceptData = true;
e.AcceptedOperation = (forceMove ? DataPackageOperation.Move :
DataPackageOperation.Copy);
e.DragUIOverride.Caption = "Drop the image to show it in this area";
break;
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
}
e.Handled = true;
// Notify XAML that now we are done
def.Complete();
}
}
// Else we let the event bubble on a possible parent target
}
Conceptos avanzados
Personalizar los comentarios visuales La única retroalimentación que arrastrar y colocar de OLE 2 ofreció fue cambiar el cursor del mouse en función de la respuesta del destino para el evento DragOver. La función moderna de arrastrar y colocar permite escenarios más avanzados, como que la información visual que se proporciona al usuario es más enriquecida. La interfaz de usuario de arrastrar consta de tres partes: contenido visual, glifo y título.
El contenido visual representa los datos que se arrastran. Podría ser el UIElement arrastrado (si el origen es una aplicación XAML); un icono estándar elegido por el sistema en función del contenido del DataPackage; o una imagen personalizada establecida por la aplicación.
El glifo refleja el tipo de operación aceptado por el destino. Puede tomar cuatro formas diferentes correspondientes a los valores del tipo DataPackageOperation. No se puede personalizar por las aplicaciones, pero se puede ocultar.
El título es una descripción proporcionada por el destino. En función de la aplicación de destino, una operación de copia, por ejemplo, puede ser agregar una canción a una lista de reproducción, cargar un archivo de OneDrive o copiar un archivo sin formato. El título permite comentarios más precisos que el glifo y desempeña un rol muy similar al de una información sobre herramientas.
En la tabla de la Figura 5 se muestra cómo el origen y el destino pueden personalizar estas partes diferentes. Cuando el puntero no se encuentra encima de un destino de colocación, la interfaz de usuario de arrastre es exactamente lo que el origen ha configurado. Cuando el puntero está encima de un destino de colocación, algunas partes del objeto visual pueden ser reemplazadas por el destino; todas las invalidaciones se borran cuando el puntero abandona el destino.
Figura 5 Personalizaciones disponibles para el origen y el destino
Origen | Destino | |
Contenido visual | Valor predeterminado = elemento arrastrado Puede usar el contenido generado por el sistema en DataPackage Puede usar cualquier mapa de bits |
Valor predeterminado = lo que se ha establecido por el origen No se puede usar el contenido generado por el sistema Puede usar cualquier mapa de bits Puede mostrar u ocultar |
Glifo | Sin acceso | Aspecto según AcceptedOperation Puede mostrar u ocultar |
Título | Sin acceso | Puede usar cualquier cadena Puede mostrar u ocultar |
Cuando se inicia una operación de arrastrar y colocar, si la aplicación de origen no intenta personalizar la interfaz de usuario de arrastre al controlador de eventos DragStarting, XAML toma una instantánea del UIElement arrastrado y la usa como el contenido de la interfaz de usuario de arrastre. El UIElement inicial se sigue mostrando en su posición original, que es un comportamiento diferente de ListView, donde los ListViewItems arrastrados se ocultan de su posición inicial. Dado que la instantánea del UIElement arrastrado se toma después de que se ha generado el evento DragStarting, es posible desencadenar un cambio de estado visual durante este evento para modificar la instantánea. (Tenga en cuenta que también se modifica el estado del UIElement e, incluso si se restaura, se puede producir un ligero parpadeo).
Al controlar un evento DragStarting, el origen de arrastre puede personalizar la información visual a través de la propiedad DragUI de la clase DragStartingEventArgs. Por ejemplo, solicitar al sistema que use el contenido de DataPackage para generar el contenido visual se realiza a través de SetContentFromDataPackage, como se muestra en la Figura 6.
Figura 6 Uso de SetContentFromDataPackage para generar contenido visual
private void DropGrid_DragStarting(UIElement sender, DragStartingEventArgs args)
{
...
if (_fileSource != null)
{
args.Data.RequestedOperation = DataPackageOperation.Copy | DataPackageOperation.Move;
args.Data.SetStorageItems(new IStorageItem[] { _fileSource });
args.DragUI.SetContentFromDataPackage();
}
else if (_bitmapSource != null)
{
args.Data.RequestedOperation = DataPackageOperation.Copy | DataPackageOperation.Move;
args.Data.SetBitmap(_bitmapSource);
args.DragUI.SetContentFromDataPackage();
}
}
Puede establecer un mapa de bits personalizado como el contenido de la interfaz de usuario de arrastre mediante dos clases diferentes: la clase BitmapImage XAML conocida o una nueva clase de Windows 10, SoftwareBitmap. Si este mapa de bits es un recurso de la aplicación, es más sencillo usar un BitmapImage e inicializarlo con el URI del recurso:
private void SampleBorder_DragStarting(UIElement sender, DragStartingEventArgs args)
{
args.Data.SetText(SourceTextBox.SelectedText);
args.DragUI.SetContentFromBitmapImage(new BitmapImage(new Uri(
"ms-appx:///Assets/cube.png", UriKind.RelativeOrAbsolute)));
}
Si el mapa de bits se debe generar sobre la marcha cuando se inicia la operación de arrastre o cuando el puntero entra en un destino de colocación, puede crearse un SoftwareBitmap desde el búfer generado por la clase RenderTargetBitmap XAML, que genera un mapa de bits que contiene la representación visual de un UIElement, como se muestra en la Figura 7. Este UIElement debe estar en el árbol visual de XAML, pero no tiene que estar en la parte visible de la página. Dado que RenderTargetBitmap realiza este procesamiento de forma asincrónica, es necesario tomar un aplazamiento aquí para que XAML sepa si el mapa de bits no está listo cuando el controlador de eventos finaliza y espera a que el aplazamiento se complete para actualizar el contenido de la interfaz de usuario de arrastrar. (Explicaremos el mecanismo de aplazamiento con mayor detenimiento en la siguiente sección de este artículo).
Figura 7 Personalización del contenido de la interfaz de usuario de arrastre con RenderTargetBitmap y SoftwareBitmap
private async void PhotoStripGrid_DragStarting(UIElement sender, DragStartingEventArgs args)
{
if ((Picture1.Picture == null) || (Picture2.Picture == null)
|| (Picture3.Picture == null) || (Picture4.Picture == null))
{
// Photo Montage is not ready
args.Cancel = true;
}
else
{
args.Data.RequestedOperation = DataPackageOperation.Copy;
args.Data.SetDataProvider(StandardDataFormats.Bitmap, ProvideContentAsBitmap);
App.SetSource(args.Data);
var deferral = args.GetDeferral();
var rtb = new RenderTargetBitmap();
const int width = 200;
int height = (int)(.5 + PhotoStripGrid.ActualHeight / PhotoStripGrid.ActualWidth
* (double)width);
await rtb.RenderAsync(PhotoStripGrid, width, height);
var buffer = await rtb.GetPixelsAsync();
var bitmap = SoftwareBitmap.CreateCopyFromBuffer(buffer, BitmapPixelFormat.Bgra8, width, height,
BitmapAlphaMode.Premultiplied);
args.DragUI.SetContentFromSoftwareBitmap(bitmap);
deferral.Complete();
}
}
Por supuesto, si ya se ha generado el SoftwareBitmap, y se puede almacenar en caché para posteriores operaciones de arrastrar y colocar, no será necesario ningún aplazamiento.
Tanto para SetContentFromBitmapImage como para SetContentFromSoftwareBitmap, puede especificar un punto de anclaje que indique cómo colocar la interfaz de usuario de arrastre en relación con la posición del puntero. Si usa la sobrecarga sin parámetro de punto de anclaje, la esquina superior izquierda del mapa de bits personalizado seguirá al puntero. El método GetPosition de DragStartingEventArgs devuelve la posición del puntero en relación con cualquier UIElement, que se puede usar para establecer la posición inicial de la interfaz de usuario de arrastre exactamente donde se encuentra el elemento UIElement.
En el lado de destino, las distintas partes del objeto visual arrastrado se pueden personalizar en controladores de eventos DragEnter o DragOver. La personalización se realiza a través de la propiedad DragUIOverride de la clase DragEventArgs, que expone cuatro métodos SetContentFrom idénticos a DragUI en el lado de origen, así como cuatro propiedades que le permiten ocultar diferentes partes de la DragUI y cambiar el título. Por último, DragUIOverride también expone un método Clear que restablece todas las invalidaciones de la DragUI realizada por el destino.
Operaciones asincrónicas La API de aplicaciones universales de Windows aplica un patrón asincrónico para todas las operaciones que pueden tardar más de unos milisegundos. Esto es especialmente importante en el caso de arrastrar y colocar, ya que dichas operaciones las controla el usuario por completo. Dada su riqueza, arrastrar y colocar usa tres patrones asincrónicos diferentes: llamadas asincrónicas, aplazamientos y devoluciones de llamada.
Las llamadas asincrónicas se usan cuando la aplicación llama a una API de sistema que puede tardar algún tiempo en completarse. Este patrón es muy conocido ahora por los desarrolladores de Windows y resulta muy sencillo con las palabras clave async y await en C# (o create_task y luego en C++). Todos los métodos que recuperan datos de DataPackage siguen este patrón, como GetBitmapAsync, que nuestra aplicación de ejemplo usa para recuperar una referencia de secuencia de imagen, como se muestra en la Figura 8.
Figura 8 Uso de llamadas asincrónicas para leer el DataPackage
private async void DropGrid_Drop(object sender, DragEventArgs e)
{
if (!App.IsSource(e.DataView))
{
bool forceMove = ((e.Modifiers & DragDropModifiers.Shift) ==
DragDropModifiers.Shift);
if (e.DataView.Contains(StandardDataFormats.Bitmap))
{
// We need to take a deferral as reading the data is asynchronous
var def = e.GetDeferral();
// Get the data
_bitmapSource = await e.DataView.GetBitmapAsync();
var imageStream = await _bitmapSource.OpenReadAsync();
var bitmapImage = new BitmapImage();
await bitmapImage.SetSourceAsync(imageStream);
// Display it
Picture = bitmapImage;
// Notify the source
e.AcceptedOperation = forceMove ? DataPackageOperation.Move :
DataPackageOperation.Copy;
e.Handled = true;
def.Complete();
}
...
}
Los aplazamientos se usan cuando el marco XAML llama de nuevo al código de una aplicación que puede emitir él mismo una llamada asincrónica antes de devolver un valor esperado por el marco de trabajo. Este patrón no se usaba ampliamente en versiones anteriores de XAML; por tanto, dediquemos tiempo a analizarlo. Cuando un botón genera un evento Click, es una llamada unidireccional en el sentido de que la aplicación no tiene que devolver ningún valor. Si se realiza una llamada asincrónica por la aplicación, su resultado estará disponible tras la finalización del controlador de eventos Click, pero esto es correcto, ya que este controlador no devuelve un valor.
Por otro lado, cuando XAML genera un DragEnter o un evento DragOver, espera que la aplicación establezca la propiedad AcceptedOperation de los argumentos del evento para indicar si se puede controlar el contenido del DataPackage. Si la aplicación solo se preocupa del tipo de datos disponible en el DataPackage, esto todavía puede hacerse de forma sincrónica, por ejemplo:
private void DropTextBox_DragOver(object sender, DragEventArgs e)
{
bool hasText = e.DataView.Contains(StandardDataFormats.Text);
e.AcceptedOperation = hasText ? DataPackageOperation.Copy :
DataPackageOperation.None;
}
Sin embargo, si, por ejemplo, la aplicación solo puede aceptar algunos tipos de archivos, no solo debe comprobar los tipos de datos que se encuentran dentro del DataPackage, también debe acceder a los datos, lo cual solo se debe hacer de manera asincrónica. Esto significa que se suspende la ejecución del código hasta que se han leído los datos y que el controlador de eventos DragEnter (o DragOver) se completará antes de que la aplicación sepa si puede aceptar los datos. Este escenario es exactamente el propósito del aplazamiento: al obtener un aplazamiento del objeto DragEventArg, la aplicación indica a XAML que aplazará parte de su procesamiento, y al completar el aplazamiento, la aplicación notifica a XAML que este procesamiento se realiza y que se han establecido las propiedades del resultado de la instancia DragEventArgs. Consulte de nuevo la Figura 4 para ver cómo nuestra aplicación de ejemplo comprueba StorageItems después de haber obtenido un aplazamiento.
El aplazamiento también se puede usar cuando la personalización del contenido de la interfaz de usuario de arrastre del lado de destino requiere operaciones asincrónicas, como el método RenderAsync de RenderTargetBitmap.
En el lado del origen de una operación de arrastrar y colocar, DragStartingEventArgs expone también un aplazamiento, cuyo propósito es permitir que la operación se inicie tan pronto como finalice el controlador de eventos (incluso si no se ha completado el aplazamiento) para proporcionar los comentarios más rápidos al usuario incluso si la creación de un mapa de bits para personalizar la interfaz de usuario de arrastre tarda algún tiempo.
Las devoluciones de llamada se usan en el DataPackage para aplazar el suministro de los datos hasta que sea realmente necesario. Con este mecanismo, la aplicación de origen puede anunciar varios formatos en el DataPackage, pero solo los datos leídos por un destino tendrá que estar preparados y transferidos. En muchos casos, nunca se llamará a la devolución de llamada, por ejemplo, si ningún destino puede entender el formato de datos correspondiente, que es una buena optimización de rendimiento.
Tenga en cuenta que, en muchos casos, ofrecer los datos reales requerirá una llamada asincrónica y, por lo tanto, el parámetro DataProviderRequest de esta devolución de llamada expone un aplazamiento para que las aplicaciones puedan notificar que necesitan más tiempo para ofrecer los datos y que los datos están disponibles, como se muestra en la Figura 9.
Figura 9 Aplazar los datos hasta que se lean realmente
private void DeferredData_DragStarting(UIElement sender,
DragStartingEventArgs args)
{
args.Data.SetDataProvider(StandardDataFormats.Text, ProvideDeferredText);
}
async void ProvideDeferredText(DataProviderRequest request)
{
var deferral = request.GetDeferral();
var file = await KnownFolders.DocumentsLibrary.GetFileAsync(fileName);
var content = await FileIO.ReadTextAsync(file);
request.SetData(content);
deferral.Complete();
}
Resumen
Al escribir una aplicación que manipula los formatos de datos estándar, como archivos, imágenes o texto, debería considerar la implementación de arrastrar y colocar ya que esta es una operación natural y conocida para los usuarios. Los conceptos básicos de arrastrar y colocar ya son familiares para quienes han programado con Windows Forms y Windows Presentation Foundation, lo que reduce la curva de aprendizaje de esta característica enriquecida, con sus conceptos específicos, como la personalización de la interfaz de usuario de arrastre y los patrones relativamente sin usar como el patrón de aplazamiento. Si solo desea admitir escenarios básicos de arrastrar y colocar, puede confiar en su experiencia anterior y tener una implementación directa o bien, si lo prefiere, puede aprovechar por completo las nuevas características para ofrecer al usuario una experiencia adaptada.
Anna Pai es un ingeniero de software en el equipo de Xbox. Anteriormente trabajó en Silverlight, Silverlight para Windows Phone y luego en XAML para Windows y Windows Phone.
Alain Zanchetta es ingeniero de software en el equipo de Windows XAML. Anteriormente fue arquitecto de la división de consultoría de Microsoft Francia.
Gracias al siguiente experto técnico de Microsoft por revisar este artículo: Clément Fauchère
Clément Fauchère es ingeniero de software en el equipo de Windows Shell de Microsoft.