Можно ли перетащить UWP StorageFile на рабочий стол, созданный с помощью CreateStreamedFileFromUriAsyc

Цель: что я хочу сделать, это перетащить GridViewItem из GridView в приложении UWP вне приложения для проводника рабочего стола. Во время события выпадения я хочу загрузить файл из Интернета и создать StorageFile который будет использоваться для заполнения DataPackage, я хочу этот StorageFile быть скопированным на рабочий стол. К сожалению, когда для UWP Drag&Drop используется отсрочка (используется SetDataProvider), как только вы выходите из окна приложения, запрос активируется, и вы должны заполнить DataPackage с объектом для передачи. Итак, мне показалось, что мне нужно будет использовать отложенный тип StorageFile создан с CreateStreamedFileFromUriAsyc,

Я не хочу предварительно загружать данные каждый раз, когда начинаю выполнять операцию перетаскивания. Я хочу загружать данные только тогда, когда я на самом деле их сбрасываю куда-то законно для копирования.

Приложение в действии, показывающее файл, перетаскиваемый на рабочий стол

  1. Я знаю, как перетащить уже существующий StorageFile из UWP в проводник (рабочий стол) с использованием отложенного запроса.
  2. Я также знаю, как создать StorageFile с помощью CreateStreamedFileFromUriAsyc это даст вам StorageFile это загружает данные только тогда, когда данные запрашиваются.

Когда я пытаюсь объединить эти две идеи, Windows Explorer выдает ошибку "интерфейс не поддерживается".

Если я использую точно такой же код, но просто получаю содержимое файла, вызывая что-то вроде GetBasicPropertiesAsync во время обработчика отложенного перетаскивания, это работает, только если я удерживаю перетаскивание на рабочем столе, пока файл не будет загружен. Я вижу, как он заканчивается, когда значок перетаскивания меняется с "запрещенного" на "копировать". Если я отпущу кнопку мыши до того, как это будет сделано, копирование не произойдет, и никаких ошибок не возникнет.

Очевидно, я бы хотел, чтобы перетаскивание загружалось без необходимости вручную запускать его в отложенном обработчике. Есть идеи? Это возможно?

(Да, я понимаю, что код для создания правильного расширения файла неправильный / неполный, но здесь это не имеет значения...)

//DragStarted Handler in constructor
DragItemsStartedCommand = ReactiveCommand.Create<DragItemsStartingEventArgs>((e) =>
        {
            _dragItems = e.Items.Cast<ItemViewModel>();
            e.Data.Properties.Title = "Transfer file";
            e.Data.Properties.Description = "desscription of transfering a file";
            e.Data.Properties.FileTypes.Add(StandardDataFormats.StorageItems);
            e.Data.SetDataProvider(Windows.ApplicationModel.DataTransfer.StandardDataFormats.StorageItems, OnDeferredStorageFileRequestedHandler);
            e.Data.RequestedOperation = DataPackageOperation.Copy;
        });


 //Deferred request handler
    async void OnDeferredStorageFileRequestedHandler(DataProviderRequest request)
    {
        DataProviderDeferral deferral = request.GetDeferral();
        try
        {
            Task<IEnumerable<StorageFile>> task = null;
            await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
            {
                task = DownloadStorageFiles();
            });
            var result = await task;
            request.SetData(result);
        }

        catch (Exception ex)
        {
            // Handle the exception
        }

        finally
        {
            deferral.Complete();
            Debug.WriteLine("deferral complete!!!");
        }

    }

//Create StorageFile with deferred loading Task
    async Task<IEnumerable<StorageFile>> DownloadStorageFiles()
    {
        List<StorageFile> storageItems = new List<StorageFile>();
        foreach (var item in _dragItems)
        {
            var request = new RestSharp.RestRequest();
        var defaultItemType = ItemType.MSWord;
        switch (item.MimeTypeTranslated)
        {
            case ItemType.GoogleDocument:
            case ItemType.GoogleSpreadsheet:
            case ItemType.GooglePresentation:
            case ItemType.GoogleDrawing:
            case ItemType.GoogleScript:
                request.Resource = $"files/{item.File.id}/export";
                request.AddParameter("mimeType", Statics.ItemTypeDictionary.First(x => x.Value == defaultItemType).Key);
                break;
            default:
                request.Resource = $"files/{item.File.id}";
                request.AddParameter("alt", "media");
                break;
        }
        string fileName = "";
        if (item.File.name.EndsWith($".{Statics.ItemExtensionDictionary[defaultItemType]}"))
            fileName = $"{item.File.name}";
        else
            fileName = $"{item.File.name}.{Statics.ItemExtensionDictionary[defaultItemType]}";
        var uri = account.Client.GetAuthorizedUriForDownload(request);

        var thumbnail = RandomAccessStreamReference.CreateFromFile(await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///StoreLogo.png")));
        var storageFileDeferred = await StorageFile.CreateStreamedFileFromUriAsync(fileName, uri , thumbnail);
        //var props = await storageFileDeferred.GetBasicPropertiesAsync();                
         storageItems.Add(file);
        }
        return storageItems;
    }

GitHub воспроизводит эту проблему: https://github.com/limefrogyank/DragDeferredFileToDesktop

  1. Первая страница - это обычное перетаскивание на рабочий стол, которое работает, потому что StorageFile (+ базовые данные) уже находится в папке активов.
  2. На второй странице показана ошибка, сгенерированная при использовании StorageFile, созданного с помощью CreateStreamedFileFromUriAsync.
  3. Третья страница использует тот же тип StorageFile, но с хаком для принудительного синхронного извлечения данных. Рабочий стол зависает на секунду, пока данные не будут готовы.

0 ответов

С момента последних обновлений Windows перетаскивание файлов хранилища в приложениях UWP автоматически обрабатывается системой.

пример GIF.

Другие вопросы по тегам