UIEventProcessors 实现拖放和多选功能

在现代的应用程序开发中,用户界面的交互性变得越来越重要。拖放和多选功能是提升用户体验的关键特性之一。本文将介绍如何使用UIEventHub以及DragDropEventProcessor和MultiSelectEventProcessor来实现这些功能。

UIEventHub 简介

UIEventHub是一个用于支持ListBox/View和TreeView的事件处理器集,它允许通过XAML语法或C#代码来注册UI处理器。以下是如何使用UIEventHub的示例。

<ListView Grid.Column="1" Grid.Row="2"> <bc:UIEventAdapter.Processors> <bc:DragDropEventProcessor EnableDrag="True" EnableDrop="True"/> <bc:MultiSelectEventProcessor UnselectAllCommand="{Binding UnselectAllCommand}"/> </bc:UIEventAdapter.Processors> </ListView> treeView.RegisterEventProcessors(new DragDropEventProcessor()); listView.RegisterEventProcessors(new DragDropEventProcessor(), new MultiSelectEventProcessor(vm1.UnselectAllCommand));

需要注意的是,TreeView不支持多选。对于拖放操作,除了注册UI处理器外,还需要实现ISupportDrag/Drop/DragHelper/DropHelper接口,以便系统能够正常工作。

IUIEventProcessor 接口

IUIEventProcessor接口允许一个应用程序(例如拖动)处理来自控件的事件。

public interface IUIEventProcessor { IEnumerable<RoutedEvent> ProcessEvents { get; } IScriptCommand OnEvent(RoutedEvent eventId); IScriptCommand OnMouseDrag { get; } // Previous method IScriptCommand OnMouseDragOver { get; } ... }

UIEventProcessor包含了多个IScriptCommand,并有一个OnEvent()方法。当触发特定事件时,会创建并运行适当的IScriptCommand(例如Control.MouseMove -> OnEvent() -> ContinueDrag)。因为IScriptCommand.Execute()可以返回另一个IScriptCommand,所以复杂的操作被分解成多个IScriptCommand。

ScriptRunner 类

ScriptRunner类实现了IScriptRunner接口,用于运行一系列IScriptCommand。

public class ScriptRunner : IScriptRunner { public void Run(Queue<IScriptCommand> cmds, ParameterDic initialParameters) { ParameterDic pd = initialParameters; while (cmds.Any()) { var current = cmds.Dequeue(); if (current.CanExecute(pd)) { var retCmd = current.Execute(pd); if (retCmd != null) cmds.Enqueue(retCmd); } else throw new Exception(String.Format("Cannot execute {0}", current)); } } }

DragDropEventProcessor

DragDropEventProcessor允许从支持ISupportDrag的DataContext拖动一个或多个对象到另一个支持ISupportDrop的DataContext。

public interface ISupportDragHelper { ISupportDrag DragHelper { get; } } public interface ISupportDrag { bool HasDraggables { get; } IEnumerable<IDraggable> GetDraggables(); DragDropEffects QueryDrag(IEnumerable<IDraggable> draggables); IDataObject GetDataObject(IEnumerable<IDraggable> draggables); void OnDragCompleted(IEnumerable<IDraggable> draggables, IDataObject da, DragDropEffects effect); }

每当用户尝试拖动时,处理器会检查DataContext是否支持ISupportDrag或ISupportDragHelper,如果HasDraggables等于true,则调用GetDraggables()和GetDataObject()获取一个数据对象,并初始化拖动(使用System.Windows.DragDrop.DoDragDrop)。

MultiSelectEventProcessor

MultiSelectEventProcessor允许通过在ListView上用鼠标拖动来选择多个项目。这是一个非常基础的功能,框架至今仍然没有提供。

<DataTemplate x:Key="dragnDropItemTemplate"> <StackPanel Orientation="Horizontal"> <TextBlock Text="{Binding Value}"/> <TextBlock Text="[ing]" Foreground="Blue" Visibility="{Binding (bc:AttachedProperties.IsSelecting), RelativeSource={RelativeSource AncestorType={x:Type ListBoxItem}}, Converter={StaticResource btvc}}"/> <TextBlock Text="[ed]" Foreground="Green" Visibility="{Binding IsSelected, Converter={StaticResource btvc}}"/> </StackPanel> </DataTemplate>

选择查找例程(FindSelectedItems)是前两篇文章的结合,它使用GridView的第一个/最后一个选中项目,支持IChildInfo的面板使用IChildInfo,否则使用HitTest。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485