前言
前面我们讲了在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());
}
}
}
看运行效果一样: