Il Datagrid WPF ha due modalità di selezione, Singola o Estesa. Il ListView di WPF ha un terzo: multiplo. Questa modalità consente di fare clic e selezionare più righe senza tenere premuto CTRL o Maiusc. Qualcuno sa come fare questo per il datagrid?Selezione multipla Datagrid WPF senza CTRL o Spazio
risposta
Questo non è supportato in DataGrid nel toolkit e sembra che sia won't be supported quando DataGrid viene fornito con .NET 4. Ancora un altro motivo per cui questo controllo non è pronto per l'uso di produzione. Vorrei andare con una di queste opzioni:
- rotolare il proprio griglia con ListView/GridView
- modificare il codice sorgente del DataGrid nel toolkit (che non dovrebbe essere troppo difficile in quanto la selezione estesa è già supportato ?)
- cercare qualsiasi delle DataGrid commerciali WPF disponibili (in genere aggiungono quantità enorme di funzionalità utili)
sono d'accordo che il DataGrid dovrebbe sostenere questo e penso che si dovrebbe file a bug/suggestion per questo comunque. Forse non è troppo tardi per entrare in .NET 4 .. :)
Si può provare questa semplice soluzione, senza dover modificare/ereditare DataGrid
controllo gestendo anteprima mouse evento come segue:
TheDataGrid.PreviewMouseLeftButtonDown +=
new MouseButtonEventHandler(TheDataGrid_PreviewMouseLeftButtonDown);
void TheDataGrid_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
// get the DataGridRow at the clicked point
var o = TryFindFromPoint<DataGridRow>(TheDataGrid, e.GetPosition(TheDataGrid));
// only handle this when Ctrl or Shift not pressed
ModifierKeys mods = Keyboard.PrimaryDevice.Modifiers;
if (o != null && ((int)(mods & ModifierKeys.Control) == 0 &&
(int)(mods & ModifierKeys.Shift) == 0))
{
o.IsSelected = !o.IsSelected;
e.Handled = true;
}
}
public static T TryFindFromPoint<T>(UIElement reference, Point point)
where T:DependencyObject
{
DependencyObject element = reference.InputHitTest(point) as DependencyObject;
if (element == null)
return null;
else if (element is T)
return (T)element;
else return TryFindParent<T>(element);
}
Il metodo TryFindFromPoint
, da un blog post by Philipp Sumi, viene utilizzato per ottenere l'istanza DataGridRow
dal punto su cui si è fatto clic.
Controllando ModifierKeys
, è ancora possibile mantenere Ctrl e Shift come comportamento predefinito.
Solo un modo per tornare indietro da questo metodo è che non è possibile fare clic e trascinare per eseguire la selezione dell'intervallo come può in origine.
Stavo creando un'applicazione con un requisito simile che avrebbe funzionato sia per il touchscreen che per il desktop. Dopo aver trascorso un po 'di tempo, la soluzione che ho trovato sembra più pulita. Nella finestra di progettazione, ho aggiunto le seguenti setter di eventi per il datagrid:
<DataGrid.RowStyle>
<Style TargetType="DataGridRow" >
<EventSetter Event="MouseEnter" Handler="MouseEnterHandler"></EventSetter>
<EventSetter Event="PreviewMouseDown" Handler="PreviewMouseDownHandler"></EventSetter>
</Style>
</DataGrid.RowStyle>
Poi nel codebehind, ho gestito gli eventi come:
private void PreviewMouseDownHandler(object sender, MouseButtonEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
DataGridRow row = Utility.GetVisualParentByType(
(FrameworkElement)e.OriginalSource, typeof(DataGridRow)) as DataGridRow;
row.IsSelected = !row.IsSelected;
e.Handled = true;
}
}
private void MouseEnterHandler(object sender, MouseEventArgs e)
{
if (e.OriginalSource is DataGridRow && e.LeftButton == MouseButtonState.Pressed)
{
DataGridRow row = e.OriginalSource as DataGridRow;
row.IsSelected = !row.IsSelected;
e.Handled = true;
}
}
Ecco il codice per il metodo di supporto GetVisualParentByType:
public static DependencyObject GetVisualParentByType(DependencyObject startObject, Type type)
{
DependencyObject parent = startObject;
while (parent != null)
{
if (type.IsInstanceOfType(parent))
break;
else
parent = VisualTreeHelper.GetParent(parent);
}
return parent;
}
Speranza che aiuta qualcun altro troppo.
Sulla base di un precedente articolo, ho scritto un ("come") Codice MVVM:
In primo luogo aggiungere questo alla tua vista principale:
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
La parte rilevante di Vista:
<DataGrid
Style="{StaticResource DataGridStyle}"
ItemsSource="{Binding Results}"
SelectionUnit="FullRow"
SnapsToDevicePixels="True"
SelectionMode="Extended"> <!--You can change selection mode with converter. It will work (i tested it.)-->
<i:Interaction.Behaviors>
<utils:EventToCommandBehavior Command="{Binding TouchCommand}"
Event="PreviewTouchDown"
PassArguments="True"></utils:EventToCommandBehavior>
<utils:EventToCommandBehavior Command="{Binding MouseCommand}"
Event="PreviewMouseDown"
PassArguments="True"></utils:EventToCommandBehavior>
</i:Interaction.Behaviors>
<DataGrid.Resources>
<Style TargetType="{x:Type DataGridRow}">
<Setter Property="IsSelected"<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background">
<Setter.Value>
<SolidColorBrush>
<SolidColorBrush.Color>
<Color A="50" R="0" G="0" B="0" />
</SolidColorBrush.Color>
</SolidColorBrush>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</DataGrid.Resources>
<DataGrid.Columns>
<!-- your columns -->
</DataGrid.Columns>
</DataGrid>
Maggiori informazioni su EventToCommandBehavior: here
In questo modo, il vostro ViewModel devono attuare questi comandi:
//i skipped the TouchCommand definition because MouseCommand runs for touch on screen too.
public RelayCommand<MouseButtonEventArgs> MouseCommand
{
get
{
return new RelayCommand<MouseButtonEventArgs>((e)=> {
if (e.LeftButton == MouseButtonState.Pressed)
{
//call this function from your utils/models
var row = FindTemplatedParentByVisualParent<DataGridRow>((FrameworkElement)e.OriginalSource,typeof(ICommandSource));
//add ICommanSource to parameters. (if actual cell contains button instead of data.) Its optional.
if(row!=null)
{
row.IsSelected = !row.IsSelected;
e.Handled = true;
}
}
});
}
}
Infine implementare un metodo (da qualche parte in Model) per trovare la riga (s).
public static T FindTemplatedParentByVisualParent<T>(FrameworkElement element,Type exceptionType = null) where T : class
{
if (element != null && (exceptionType == null || element.TemplatedParent == null || (exceptionType != null && element.TemplatedParent !=null && !exceptionType.IsAssignableFrom(element.TemplatedParent.GetType()))))
{
Type type = typeof(T);
if (type.IsInstanceOfType(element.TemplatedParent))
{
return (element.TemplatedParent as T);
}
else
{
return FindTemplatedParentByVisualParent<T>((FrameworkElement)VisualTreeHelper.GetParent(element));
}
}
else
return null;
}
Questa soluzione funziona perfettamente per me quindi spero che possa essere d'aiuto anche per voi.
- 1. Prevenire selezione di riga multipla in WPF DataGrid
- 2. WPF trascinamento della selezione su DataGrid
- 3. WPF DataGrid, Copia negli Appunti dopo Ctrl + C, OnCopyingRowClipboardContent
- 4. VirtualizingStackPanel + MVVM + multipla selezione
- 5. Selezione multipla in Vim
- 6. WAM XAML: Come disabilitare la selezione multipla in un DataGrid?
- 7. Spinner selezione multipla in Android senza AlertDialog
- 8. Migliora prestazioni DataGrid WPF
- 9. Seleziona tutto WPF DataGrid
- 10. SQL deadlock tra selezione/aggiornamento o selezione multipla
- 11. WPF Toolkit Datagrid - come si disattiva la selezione?
- 12. Raggruppamento con trascinamento della selezione in WPF DataGrid
- 13. Come annullare la selezione di Datagrid evento modificato in WPF?
- 14. JavaFX ListView Selezione multipla
- 15. Disabilita selezione multipla?
- 16. JcomboBox selezione multipla
- 17. QListWidget e selezione multipla
- 18. Jquery selezione multipla
- 19. WPF DataGrid filter
- 20. UITableView - Selezione multipla E selezione singola
- 21. WPF datagrid incollando
- 22. Prestazioni Datagrid WPF
- 23. Selezione multipla in un TreeView
- 24. WPF GroupBox senza spazio di testa
- 25. WPF ToolKit DataGrid Performance
- 26. WPF Numero riga Datagrid
- 27. colonna combobox datagrid wpf
- 28. WPF DataGrid SelectedItem
- 29. Datagrid modificabile in WPF
- 30. Come si nasconde selettore riga datagrid wpf