我在我的應用程序中做了這個,當你必須選擇30個複選框時非常方便。
爲此,我自己處理預覽鼠標事件:PreviewMouseLeftButtonDown,PreviewMouseMove,PreviewMouseLeftButtonUp。
在PreviewMouseLeftButtonDown:我得到相對於控件的鼠標位置。
在PreviewMouseMove中:如果我距離firstPoint足夠遠,我會從開始到當前位置繪製一個矩形。然後我在複選框中迭代,看看他們是否與矩形相交,並且如果是的話突出顯示它們(所以用戶知道哪些chexboxes將交換)
在PreviewMouseLeftButtonUp中:我爲相交CheckBoxes做交換。
如果它可以幫助你,這裏是我使用的代碼。它不是MVVM(:-)),但工作正常,它可能會給你想法。它是從vb.net代碼自動翻譯。
爲了使它工作,你需要在你的CheckBoxes之上有一個Canvas(例如在同一個網格單元格內),屬性IsHitTestVisible =「False」。
在這個Canvas中,使用適當的填充和描邊放置一個Rectangle nammed「SelectionRectangle」,但使用0.0 Opacity。
// '' <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布爾值和良好的列/行平衡的選擇。
感謝您的幫助。雖然這不是我尋找的優雅解決方案,但它比我想出的任何東西都要好。 – lambdaman
很高興我能幫忙:-)看到我的編輯。 – GameAlchemist