Bảng dữ liệu WPF có hai chế độ lựa chọn, một hoặc mở rộng. Danh sách WPF có thứ ba - Nhiều. Chế độ này cho phép bạn nhấp và chọn nhiều hàng mà không cần nhấn CTRL hoặc Shift. Bất cứ ai cũng biết làm thế nào để làm điều này cho DataGrid?Đa mục tiêu WPF Nhiều lựa chọn không có CTRL hoặc không gian
Trả lời
Điều này không được hỗ trợ trong DataGrid trong bộ công cụ, và có vẻ như nó won't be supported khi DataGrid được vận chuyển với .NET 4. Tuy nhiên, một lý do khác tại sao sự kiểm soát này không sẵn sàng cho việc sử dụng sản xuất. Tôi sẽ đi với một trong các tùy chọn này:
- cuộn lưới của riêng bạn với ListView/GridView
- Sửa đổi mã nguồn của DataGrid trong bộ công cụ (nó không nên quá khắt khe từ lựa chọn mở rộng đã được hỗ trợ ?)
- Hãy tìm bất kỳ của lưới dữ liệu sủ WPF thương mại có sẵn (họ thường thêm số tiền rất lớn của các chức năng hữu ích)
tôi đồng ý rằng DataGrid nên hỗ trợ này và tôi nghĩ bạn nên file a bug/suggestion cho điều này anyway. Có lẽ nó không quá muộn để làm cho nó vào NET 4 .. :)
Bạn có thể thử phương pháp đơn giản này mà không cần phải sửa đổi/kế thừa DataGrid
kiểm soát bằng cách xử lý preview chuột xuống sự kiện như sau:
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);
}
Phương pháp TryFindFromPoint
, từ một số blog post by Philipp Sumi, được sử dụng để lấy trường hợp DataGridRow
từ điểm bạn đã nhấp.
Bằng cách kiểm tra ModifierKeys
, bạn vẫn có thể giữ Ctrl và Shift làm hành vi mặc định.
Chỉ một điểm vẽ từ phương pháp này là bạn không thể nhấp và kéo để thực hiện phạm vi được chọn giống như ban đầu.
Tôi đã tạo một ứng dụng có yêu cầu tương tự sẽ hoạt động cho cả màn hình cảm ứng và máy tính để bàn. Sau khi dành chút thời gian cho nó, giải pháp tôi đưa ra có vẻ sạch hơn. Trong nhà thiết kế, tôi đã thêm các setters sự kiện sau đây để DataGrid:
<DataGrid.RowStyle>
<Style TargetType="DataGridRow" >
<EventSetter Event="MouseEnter" Handler="MouseEnterHandler"></EventSetter>
<EventSetter Event="PreviewMouseDown" Handler="PreviewMouseDownHandler"></EventSetter>
</Style>
</DataGrid.RowStyle>
Sau đó, trong codebehind, tôi xử lý các sự kiện như:
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;
}
}
Đây là mã cho phương thức helper 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;
}
Hy vọng nó cũng giúp người khác.
Dựa trên một bài viết trước, tôi đã viết một ("like") mã MVVM:
Thứ nhất thêm video này vào Xem chính của bạn:
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
Phần liên quan của Xem:
<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>
Thông tin khác về EventToCommandBehavior: here
Bằng cách này, ViewModel của bạn phải thực hiện các lệnh:
//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;
}
}
});
}
}
Cuối cùng thực hiện một phương pháp (ở đâu đó trong Model) để tìm hàng (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;
}
Giải pháp này làm việc hoàn hảo vì vậy tôi hy vọng nó cũng sẽ giúp ích cho bạn.
- 1. WPF TreeView với nhiều lựa chọn
- 2. Cấu hình ListBox trong WPF để tôi có thể chọn nhiều mục mà không cần giữ phím CTRL
- 3. Ngăn việc lựa chọn hàng nhiều trong WPF DataGrid
- 4. tiêu chí lựa chọn jquery hoặc silverlight
- 5. QT - đa lựa chọn
- 6. UICollectionView với nhiều lựa chọn sẽ không chọn nhiều hơn một chục mục
- 7. Tắt đa lựa chọn?
- 8. WPF GroupBox với không gian tiêu đề
- 9. Nhiều lựa chọn trong Vim
- 10. Chỉ mục nhiều cột có hoạt động đối với các lựa chọn cột đơn không?
- 11. Grails g: chọn không có lựa chọn
- 12. WPF ListBoxItem lựa chọn vấn đề
- 13. Lập trình lựa chọn các mục trong Danh sách WPF
- 14. Nhiều lựa chọn trên WinForms
- 15. Quản lý nhiều lựa chọn với MVVM
- 16. Lựa chọn Hộp danh sách WPF Màu
- 17. PThread có phải là lựa chọn tốt cho chương trình đa luồng đa luồng C/C++ không?
- 18. JcomboBox nhiều lựa chọn
- 19. CHỌN phần tử theo kiểu hiển thị nhiều lựa chọn mà không cho phép nhiều lựa chọn
- 20. Cách chọn các tùy chọn không liên tiếp của nhiều lựa chọn bằng bàn phím trong IE
- 21. Tùy chỉnh TreeView để cho phép đa lựa chọn
- 22. Tách biệt nhiều hàng lựa chọn
- 23. Kendo ui Xác thực đa lựa chọn
- 24. Hộp kiểm chuyển đổi (nhiều lựa chọn) thành nút radio hoặc hộp kiểm có lựa chọn duy nhất?
- 25. Formtastic/ActiveAdmin đa lựa chọn nhiều đến nhiều vấn đề liên kết hộp kiểm
- 26. django lựa chọn mô hình lựa chọn như một hộp chọn đa
- 27. LINQ có phải là một lựa chọn hợp lệ không?
- 28. Nhiều lựa chọn giá trị sửa mẫu lựa chọn
- 29. Đa luồng so với Đa phiên bản - Lựa chọn nào?
- 30. Thẻ mẫu MVC Spring: Có cách nào tiêu chuẩn để thêm mục "Không chọn" không?