You could try to refer to the following method to implement multiple selection without Ctrl in the DataGrid. For more methods, you can refer here.
I set the style background of the DataGridRow to pink to distinguish whether the item is selected.
The code of xaml:
<StackPanel Background="AliceBlue" >
<DataGrid Name="dataGrid" ItemsSource="{Binding Persons}" BorderBrush="Black"
SelectionMode="Extended" SelectionUnit="FullRow"
BorderThickness="1" AutoGenerateColumns="False" CanUserAddRows="True" >
<DataGrid.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent"/>
</DataGrid.Resources>
<DataGrid.RowStyle>
<Style TargetType="DataGridRow" >
<EventSetter Event="MouseEnter" Handler="MouseEnterHandler"></EventSetter>
<EventSetter Event="PreviewMouseDown" Handler="PreviewMouseDownHandler"></EventSetter>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="Pink"/>
</Trigger>
</Style.Triggers>
</Style>
</DataGrid.RowStyle>
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding PersonName}" Header="Name"/>
</DataGrid.Columns>
</DataGrid>
</StackPanel>
The code of xmal.cs:
using System.Windows;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System;
using System.Windows.Controls;
using System.Runtime.CompilerServices;
using System.Windows.Input;
using System.Windows.Media;
namespace SelectDataGridItems
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext=new ViewModel();
}
private void MouseEnterHandler(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed &&
e.OriginalSource is DataGridRow row)
{
row.IsSelected = !row.IsSelected;
e.Handled = true;
}
}
private void PreviewMouseDownHandler(object sender, MouseButtonEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed && e.OriginalSource is FrameworkElement element &&
GetVisualParentOfType<DataGridRow>(element) is DataGridRow row)
{
row.IsSelected = !row.IsSelected;
e.Handled = true;
}
}
private static DependencyObject GetVisualParentOfType<T>(DependencyObject startObject)
{
DependencyObject parent = startObject;
while (IsNotNullAndNotOfType<T>(parent))
{
parent = VisualTreeHelper.GetParent(parent);
}
return parent is T ? parent : throw new Exception($"Parent of type {typeof(T)} could not be found");
}
private static bool IsNotNullAndNotOfType<T>(DependencyObject obj)
{
return obj != null && !(obj is T);
}
}
public class ViewModel : INotifyPropertyChanged
{
private ObservableCollection<Person> persons = new ObservableCollection<Person>();
public ObservableCollection<Person> Persons
{
get { return persons; }
set { persons = value;
OnPropertyChanged("Persons");}
}
public ViewModel()
{
Persons.Add(new Person { PersonName="john"});
Persons.Add(new Person { PersonName="joe"});
Persons.Add(new Person { PersonName="johnny"});
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string name = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
}
public class Person : INotifyPropertyChanged
{
private string name;
public string PersonName
{
get { return name; }
set
{
name = value;
OnPropertyChanged("PersonName");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string name = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
}
}
The picture of result :

If the response is helpful, please click "Accept Answer" and upvote it.
Note: Please follow the steps in our [documentation][5] to enable e-mail notifications if you want to receive the related email notification for this thread.
[5]: https://learn.microsoft.com/en-us/answers/articles/67444/email-notifications.html