Почему перетаскивание файлов не работает в окне приложения Avalonia? - PullRequest
0 голосов
/ 06 августа 2020

Я пытаюсь реализовать Drag & Drop с файлами на ListBox, который содержится в Window проекта Avalonia.
Поскольку я не мог заставить его работать и Я подумал, что ListBox, возможно, является частным случаем, я попытался сделать аналогичный пример, например, из ControlCatalogStandalone .
Хотя код в ControlCatalogStandalone работает, как ожидалось, практически тот же код в моем тестовом приложении не работает должным образом.
Соответствующий код в ControlCatalogStandalone принадлежит UserControl, тогда как в моем приложении он принадлежит MainWindow. Может ли это быть причиной неправильного поведения?
Я создал новое приложение Avalonia MVVM на основе пакетов NuGet 0.9.11 в Visual Studio 2019.
Я также пробовал версия 0.10.0-preview2 напрасно.
Это файл XAML:

<Window xmlns="https://github.com/avaloniaui"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:vm="clr-namespace:DragAndDropTests.ViewModels;assembly=DragAndDropTests"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d" Width="400" Height="200"
        x:Class="DragAndDropTests.Views.MainWindow"
        Icon="/Assets/avalonia-logo.ico"
        Title="DragAndDropTests">

    <Design.DataContext>
        <vm:MainWindowViewModel/>
    </Design.DataContext>

    <StackPanel Orientation="Vertical" Spacing="4">
        <TextBlock Classes="h1">Drag+Drop</TextBlock>
        <TextBlock Classes="h2">Example of Drag+Drop capabilities</TextBlock>

        <StackPanel Orientation="Horizontal"
                Margin="0,16,0,0"
                HorizontalAlignment="Center"
                Spacing="16">
            <Border BorderBrush="{DynamicResource ThemeAccentBrush}" BorderThickness="2" Padding="16" Name="DragMe">
                <TextBlock Name="DragState">Drag Me</TextBlock>
            </Border>
            <Border Background="{DynamicResource ThemeAccentBrush2}" Padding="16"
                    DragDrop.AllowDrop="True">
                <TextBlock Name="DropState">Drop some text or files here</TextBlock>
            </Border>
        </StackPanel>
    </StackPanel>

</Window>

А это скрытый код:

using Avalonia;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Markup.Xaml;
using System;
using System.Diagnostics;

namespace DragAndDropTests.Views
{
    public class MainWindow : Window
    {
        private TextBlock _DropState;
        private TextBlock _DragState;
        private Border _DragMe;
        private int DragCount = 0;

        public MainWindow()
        {
            Debug.WriteLine("MainWindow");
            InitializeComponent();
#if DEBUG
            this.AttachDevTools();
#endif
            _DragMe.PointerPressed += DoDrag;

            AddHandler(DragDrop.DropEvent, Drop);
            AddHandler(DragDrop.DragOverEvent, DragOver);
        }

        private async void DoDrag(object sender, Avalonia.Input.PointerPressedEventArgs e)
        {
            Debug.WriteLine("DoDrag");
            DataObject dragData = new DataObject();
            dragData.Set(DataFormats.Text, $"You have dragged text {++DragCount} times");

            var result = await DragDrop.DoDragDrop(e, dragData, DragDropEffects.Copy);
            switch (result)
            {
                case DragDropEffects.Copy:
                    _DragState.Text = "The text was copied"; break;
                case DragDropEffects.Link:
                    _DragState.Text = "The text was linked"; break;
                case DragDropEffects.None:
                    _DragState.Text = "The drag operation was canceled"; break;
            }
        }

        private void DragOver(object sender, DragEventArgs e)
        {
            Debug.WriteLine("DragOver");
            // Only allow Copy or Link as Drop Operations.
            e.DragEffects = e.DragEffects & (DragDropEffects.Copy | DragDropEffects.Link);

            // Only allow if the dragged data contains text or filenames.
            if (!e.Data.Contains(DataFormats.Text) && !e.Data.Contains(DataFormats.FileNames))
                e.DragEffects = DragDropEffects.None;
        }

        private void Drop(object sender, DragEventArgs e)
        {
            Debug.WriteLine("Drop");
            if (e.Data.Contains(DataFormats.Text))
                _DropState.Text = e.Data.GetText();
            else if (e.Data.Contains(DataFormats.FileNames))
                _DropState.Text = string.Join(Environment.NewLine, e.Data.GetFileNames());
        }

        private void InitializeComponent()
        {
            Debug.WriteLine("InitializeComponent");
            AvaloniaXamlLoader.Load(this);

            _DropState = this.Find<TextBlock>("DropState");
            _DragState = this.Find<TextBlock>("DragState");
            _DragMe = this.Find<Border>("DragMe");
        }
    }
}

Перетаскивание в приложении хорошо работает в ControlCatalogStandalone и в моем приложении.
Последовательность событий DoDrag, DragOver, DragOver,…, Drop в в этом случае.

Перетаскивание файла из Windows Explorer в ControlCatalogStandalone работает хорошо.
Последовательность событий: DragOver, DragOver,…, Drop

Перетаскивание файла из Windows Explorer в мое приложение не работает.
Здесь не вызывается ни одно из ожидаемых событий.

Что не так с моим тестовым приложением?

...