C# Wpf Items控件中类似Excel的拖动选择

C# Wpf Items控件中类似Excel的拖动选择,c#,wpf,drag,itemscontrol,C#,Wpf,Drag,Itemscontrol,我希望在Wpf items控件中创建一个选择矩形,就像在MS Excel中一样。我已经查看了装饰器和应用程序,但没有得到什么帮助。我需要在使用鼠标选择的单元格周围设置厚边框(查看屏幕截图) 我为您提供了一个解决方案,它似乎可以很好地使用一个附加属性来附加到项目控件(如listbox)。 代码仅通过检查所选项目是否按索引连续来猜测它们是否连续。比如说一个带有一些行数的uniformgrid将不起作用,但这应该可以让您开始 使用System.Collections.Generic; 使用System

我希望在Wpf items控件中创建一个选择矩形,就像在MS Excel中一样。我已经查看了装饰器和应用程序,但没有得到什么帮助。我需要在使用鼠标选择的单元格周围设置厚边框(查看屏幕截图)


我为您提供了一个解决方案,它似乎可以很好地使用一个附加属性来附加到项目控件(如listbox)。 代码仅通过检查所选项目是否按索引连续来猜测它们是否连续。比如说一个带有一些行数的uniformgrid将不起作用,但这应该可以让您开始

使用System.Collections.Generic;
使用System.Linq;
使用System.Windows;
使用System.Windows.Controls;
使用System.Windows.Controls.Primitives;
使用System.Windows.Documents;
使用System.Windows.Media;
命名空间WpfApplication2
{
/// 
///MainWindow.xaml的交互逻辑
/// 
公共部分类主窗口:窗口
{
公共主窗口()
{
初始化组件();
}
}
公共密封类选择装饰器:装饰器
{
私有静态只读字典_Dictionary=newdictionary();
私有静态只读笔_Pen=CreatePen();
public static readonly dependencProperty useAdonderProperty=dependencProperty.RegisterAttached(“useAdonder”)、typeof(bool)、typeof(selectionadrner),
新的物业管理数据(OnUseAdornerChanged);
静态void AttachToScrollViewer(选择器)
{
ScrollViewer=GetScrollViewer(选择器);
如果(查看器!=null)
{
Tag=选择器;
viewer.ScrollChanged+=viewer\u ScrollChanged;
}
}
私有静态笔CreatePen()
{
钢笔=新钢笔(刷子。黑色,2.0);
笔。冻结();
回程笔;
}
专用静态空心分离装饰器(选择器)
{
选择装饰器;
if(_dictionary.TryGetValue(选择器,out装饰符))
{
装饰器。_装饰器层。移除(装饰器);
_删除(选择器);
}
}
专用静态选择器或GetAdorner(选择器)
{
选择装饰器;
if(!\u dictionary.TryGetValue(选择器、输出装饰器))
{
_添加(选择器,装饰器=新的选择器或选择器);
}
返回装饰器;
}
私有静态Rect GetBounds(选择器、UIElement containerElement)
{
Rect-bounds=VisualTreeHelper.GetDescendantBounds(containerElement);
返回新的Rect(containerElement.TranslatePoint(bounds.TopLeft,选择器),bounds.Size);
}
私有静态ScrollViewer GetScrollViewer(DependencyObject d)
{
列表=新列表();
foreach(Enumerable.Range(0,VisualTreeHelper.GetChildrenCount(d))中的DependencyObject子对象。选择(索引=>VisualTreeHelper.GetChild(d,索引)))
{
ScrollViewer=作为ScrollViewer的子级;
如果(查看器!=null)
{
返回查看器;
}
列表。添加(子项);
}
返回列表.Select(GetScrollViewer).FirstOrDefault(查看器=>viewer!=null);
}
私有静态无效ONUSADORNERCHANGED(DependencyObject d、DependencyPropertyChangedEventArgs e)
{
选择器=d作为选择器;
if(选择器!=null)
{
如果(((bool)e.NewValue))
{
selector.SelectionChanged+=selector\u SelectionChanged;
如果(!selector.IsLoaded)
{
选择器已加载+=选择器已加载;
}
其他的
{
AttachToScrollViewer(选择器);
}
进程选择(选择器);
}
其他的
{
selector.SelectionChanged-=selector\u SelectionChanged;
如果(!selector.IsLoaded)
{
selector.Loaded-=selector_Loaded;
}
其他的
{
ScrollViewer=GetScrollViewer(选择器);
如果(查看器!=null)
{
viewer.ScrollChanged-=viewer\u ScrollChanged;
}
}
拆卸器(选择器);
}
}
}
私有静态void ProcessSelection(选择器)
{
ListBox ListBox=选择器作为ListBox;
if(listBox!=null&&listBox.SelectionMode!=SelectionMode.Single)
{
如果(listBox.SelectedItems.Count!=0)
{
object[]selectedItems=新对象[listBox.selectedItems.Count];
listBox.SelectedItems.CopyTo(SelectedItems,0);
进程选择(选择器,selectedItems);
返回;
}
}
else if(selector.SelectedItem!=null)
{
ProcessSelection(选择器,新[]{selector.SelectedItem});
返回;
}
拆卸器(选择器);
}
私有静态void进程选择(选择器、IEnumerable selectedItems)
{
列表容器=新列表();
列表索引=新列表();
foreach(selectedItems中的DependencyObject容器
.Select(selectedItem=>selector.ItemContainerGenerator.ContainerFromItem