前言
前面我们讲了在Avalonia中如何将View事件映射到ViewModel层感兴趣的读者可以看一下,本章我们将讲一下在Avalonia框架下如何实现文件和文字的拖拽到指定区域进行处理和上传。
先看效果
界面设计比较简单,还是在前一张的基础上加了一个指定区域,这个区域负责接收我们拖拽上面的内容。
方案一
第一种方案是通过后台代码的方式给指定控件注册相关AddHandler
方法动态注册DragDrop.DropEvent
,代码如下:
public ViewB(){InitializeComponent();b1.AddHandler(DragDrop.DropEvent, Drop);}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());else if(e.Data.Contains(DataFormats.Files))_DropState.Text = string.Join(Environment.NewLine, e.Data.GetFiles().Select(u=>u.Name));}
展示效果如下:
这种模式破坏了MVVM模式,感觉不是太完美。
方案二
通过自定义Handle处理来处理,我们通过定义FileDropHandler来统一处理拖拽上来的信息,处理方式如下:
using Avalonia.Input;
using Avalonia.Xaml.Interactions.DragAndDrop;
using AvaloniaTest.ViewModels;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace AvaloniaTest.Behaviors
{public class FileDropHandler: DropHandlerBase{public override void Drop(object? sender, DragEventArgs e, object? sourceContext, object? targetContext){if (!(targetContext is ViewBViewModel)){return;}var vm = (ViewBViewModel)targetContext;var type = e.Data.GetType();var i = e.Data.GetText();vm.FileName = i;var file = e.Data.GetFiles();if (file == null){return;}var names = file.Select(x => x.Name).ToList();vm.FileName = string.Join(Environment.NewLine, names);e.Data.ToString();}public override bool Execute(object? sender, DragEventArgs e, object? sourceContext, object? targetContext, object? state){return base.Execute(sender, e, sourceContext, targetContext, state);}public override void Enter(object? sender, DragEventArgs e, object? sourceContext, object? targetContext){base.Enter(sender, e, sourceContext, targetContext);}public override bool Validate(object? sender, DragEventArgs e, object? sourceContext, object? targetContext, object? state){return true;}}
}
前端代码如下:
<UserControl xmlns="https://github.com/avaloniaui"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:prism="http://prismlibrary.com/"xmlns:i="clr-namespace:Avalonia.Xaml.Interactivity;assembly=Avalonia.Xaml.Interactivity"xmlns:ia="clr-namespace:Avalonia.Xaml.Interactions.Core;assembly=Avalonia.Xaml.Interactions"xmlns:idd="clr-namespace:Avalonia.Xaml.Interactions.DragAndDrop;assembly=Avalonia.Xaml.Interactions.DragAndDrop"xmlns:b="using:AvaloniaTest.Behaviors"prism:ViewModelLocator.AutoWireViewModel="True"mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"x:Class="AvaloniaTest.Views.ViewB" Background="Green"><i:Interaction.Behaviors><ia:EventTriggerBehavior EventName="Loaded"><ia:InvokeCommandAction Command="{Binding OnLoad}"></ia:InvokeCommandAction></ia:EventTriggerBehavior></i:Interaction.Behaviors><UserControl.Styles><Style Selector="Border.FileDragAndDrop1"><Style.Resources><b:FileDropHandler x:Key="FileDropHandler" /></Style.Resources><Setter Property="(i:Interaction.Behaviors)"><i:BehaviorCollectionTemplate><i:BehaviorCollection><idd:ContextDropBehavior Handler="{StaticResource FileDropHandler}" /></i:BehaviorCollection></i:BehaviorCollectionTemplate></Setter></Style></UserControl.Styles><StackPanel><TextBlock Text="{Binding Title}"></TextBlock><Border BorderThickness="1" BorderBrush="White" Width="100" Height="100" DragDrop.AllowDrop="True" CornerRadius="20" Classes="FileDragAndDrop" Cursor="DragMove" Name="b1"><Grid><TextBlock Text="Drag" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="White" FontSize="20"></TextBlock></Grid></Border><TextBlock x:Name="_DropState"></TextBlock><TextBlock Text="{Binding FileName}"></TextBlock></StackPanel></UserControl>
ViewModel代码如下:
using Avalonia.Input;
using Prism.Commands;
using Prism.Regions;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace AvaloniaTest.ViewModels
{public class ViewBViewModel : ViewModelBase, INavigationAware{private string _title = "ViewB";public string Title{get => _title;set{SetProperty(ref _title, value);}}private string _FileName;public string FileName{get => _FileName;set{SetProperty(ref _FileName, value);}}public bool IsNavigationTarget(NavigationContext navigationContext){return true;}public void OnNavigatedFrom(NavigationContext navigationContext){}public void OnNavigatedTo(NavigationContext navigationContext){}private DelegateCommand _onLoad;public DelegateCommand OnLoad => _onLoad ?? (_onLoad=new DelegateCommand(() => {Debug.WriteLine("OnLoad is run!");}));public void Grid_Click(object sender, object e){try{Debug.WriteLine("click触发");}catch (System.Exception){}}public void FilesDataGrid_Drop(object sender, DragEventArgs e){Debug.WriteLine(e.ToString());}}
}
看运行效果一样: