我在我的应用程序中这样做了,当您必须选择 30 个复选框时非常方便。
为此,我自己处理了预览鼠标事件:PreviewMouseLeftButtonDown、PreviewMouseMove、PreviewMouseLeftButtonUp。
在 PreviewMouseLeftButtonDown :我得到鼠标相对于控件的位置。
在 PreviewMouseMove 中:如果我离 firstPoint 足够远,我会从开始到当前位置绘制一个矩形。然后我在 CheckBoxes 中进行迭代,查看它们是否与矩形相交,如果是,则突出显示它们(这样用户就知道 chesboxes 将交换)
在 PreviewMouseLeftButtonUp 中:我为相交的 CheckBoxes 进行交换。
如果它可以帮助你,这是我使用的代码。它不是 MVVM (:-)) 但工作正常,它可能会给你一些想法。它是 vb.net 代码的自动翻译。
要使其工作,您需要在 CheckBoxes 顶部有一个 Canvas(例如,=在同一个网格单元内),其属性为 IsHitTestVisible="False" 。
在这个画布中,放置一个名为“SelectionRectangle”的矩形,它具有适当的填充和描边,但不透明度为 0.0。
// '' <summary>
// '' When Left Mouse button is pressed, remember where the mouse move start
// '' </summary>
private void EditedItems_PreviewMouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e) {
StartPoint = Mouse.GetPosition(this);
}
// '' <summary>
// '' When mouse move, update the highlight of the selected items.
// '' </summary>
private void EditedItems_PreviewMouseMove(object sender, System.Windows.Input.MouseEventArgs e) {
if ((StartPoint == null)) {
return;
}
PointWhereMouseIs = Mouse.GetPosition(this);
Rect SelectedRect = new Rect(StartPoint, PointWhereMouseIs);
if (((SelectedRect.Width < 20)
&& (SelectedRect.Height < 20))) {
return;
}
// show the rectangle again
Canvas.SetLeft(SelectionRectangle, Math.Min(StartPoint.X, PointWhereMouseIs.X));
Canvas.SetTop(SelectionRectangle, Math.Min(StartPoint.Y, PointWhereMouseIs.Y));
SelectionRectangle.Width = Math.Abs((PointWhereMouseIs.X - StartPoint.X));
SelectionRectangle.Height = Math.Abs((PointWhereMouseIs.Y - StartPoint.Y));
foreach (CheckBox ThisChkBox in EditedItems.Children) {
object rectBounds = VisualTreeHelper.GetDescendantBounds(ThisChkBox);
Vector vector = VisualTreeHelper.GetOffset(ThisChkBox);
rectBounds.Offset(vector);
if (rectBounds.IntersectsWith(SelectedRect)) {
((TextBlock)(ThisChkBox.Content)).Background = Brushes.LightGreen;
}
else {
((TextBlock)(ThisChkBox.Content)).Background = Brushes.Transparent;
}
}
}
// '' <summary>
// '' When Left Mouse button is released, change all CheckBoxes values. (Or do nothing if it is a small move -->
// '' click will be handled in a standard way.)
// '' </summary>
private void EditedItems_PreviewMouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e) {
PointWhereMouseIs = Mouse.GetPosition(this);
Rect SelectedRect = new Rect(StartPoint, PointWhereMouseIs);
StartPoint = null;
SelectionRectangle.Opacity = 0;
// hide the rectangle again
if (((SelectedRect.Width < 20)
&& (SelectedRect.Height < 20))) {
return;
}
foreach (CheckBox ThisEditedItem in EditedItems.Children) {
object rectBounds = VisualTreeHelper.GetDescendantBounds(ThisEditedItem);
Vector vector = VisualTreeHelper.GetOffset(ThisEditedItem);
rectBounds.Offset(vector);
if (rectBounds.IntersectsWith(SelectedRect)) {
ThisEditedItem.IsChecked = !ThisEditedItem.IsChecked;
}
((TextBlock)(ThisEditedItem.Content)).Background = Brushes.Transparent;
}
}
编辑:我在用户控件中使用了该代码。此控件将布尔值列表和字符串列表(标题)作为参数,并(使用 WrapPanel)构建具有正确标题的 CheckBox 数组。所以你可以用矩形选择/取消选择,还有两个按钮可以选中/取消选中所有。我还尝试保持良好的列/行比率以处理具有良好列/行平衡的 7 到 200 个布尔值的选择。
![在窗口中使用 BooleanEdit 用户控件的示例](https://i.stack.imgur.com/MlG2h.jpg)