私は自分のアプリケーションでこれを行いました。たとえば、30 個のチェックボックスを選択する必要がある場合に非常に便利です。
これを行うために、プレビュー マウス イベントを自分で処理しました: PreviewMouseLeftButtonDown、PreviewMouseMove、PreviewMouseLeftButtonUp。
PreviewMouseLeftButtonDown : コントロールに対するマウスの位置を取得します。
PreviewMouseMove で: firstPoint から十分に離れている場合、開始位置から現在の位置まで四角形を描画します。次に、CheckBoxes を反復処理し、それらが四角形と交差するかどうかを確認し、交差する場合は強調表示します (したがって、ユーザーは、どのチェック ボックスがスワップされるかを知ることができます) 
。  
それがあなたを助けることができるなら、ここに私が使用するコードがあります。MVVM (:-)) ではありませんが、問題なく動作します。アイデアが得られるかもしれません。これは、vb.net コードからの自動翻訳です。  
これを機能させるには、プロパティ IsHitTestVisible="False" を使用して、CheckBoxes の上 (= たとえば同じグリッド セル内) に Canvas が必要です。
この Canvas 内に、「SelectionRectangle」という名前の Rectangle を適切な塗りと線で配置しますが、不透明度は 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;
    }
}
編集:ユーザーコントロール内でそのコードを使用しました。このコントロールは、ブール値のリストと文字列 (キャプション) のリストを引数として取り、適切なキャプションを持つ CheckBox の配列を (WrapPanel を使用して) 構築します。そのため、長方形で選択/選択解除できます。また、すべてをオン/オフするための2つのボタンもあります。また、列と行のバランスが取れた 7 ~ 200 個のブール値の選択を処理するために、列と行の比率を適切に保つようにしました。
