在我的项目中,我遇到一种情况,需要在数据网格的行上进行拖放.在数据网格中,我有一列用于选择或取消选择特定项目的复选框.
XAML文件
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:local="clr-namespace:WpfApplication1"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<local:ProductCollection x:Key="ProductList"/>
</Window.Resources>
<Grid DataContext="{Binding Source={StaticResource ProductList}}">
<DataGrid d:LayoutOverrides="Width" Margin="0,28,0,0" Name="productsDataGrid"
AutoGenerateColumns="False" ItemsSource="{Binding}"
SelectionMode="Extended" ColumnWidth="*" AllowDrop="True" >
<DataGrid.Columns>
<DataGridTemplateColumn Header="CheckBoxColumn1">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding IsActive}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Binding="{Binding ProductId}" Header="ProductId"></DataGridTextColumn>
<DataGridTextColumn Binding="{Binding ProductName}" Header="ProductName"></DataGridTextColumn>
<DataGridTextColumn Binding="{Binding ProductPrice}" Header="ProductPrice"></DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
<TextBlock TextWrapping="Wrap" Text="DataGrid Row Drag And Drop Sample" VerticalAlignment="Top" Margin="3,1,0,0" Height="24" HorizontalAlignment="Left" Width="268" FontSize="14.667" FontWeight="Bold" FontStyle="Italic"/>
</Grid>
</Window>
CodeBehind文件
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Controls.Primitives;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
///
public delegate Point GetPosition(IInputElement element);
public partial class MainWindow : Window
{
int rowIndex = -1;
public MainWindow()
{
InitializeComponent();
productsDataGrid.PreviewMouseLeftButtonDown += new MouseButtonEventHandler(productsDataGrid_PreviewMouseLeftButtonDown);
productsDataGrid.Drop += new DragEventHandler(productsDataGrid_Drop);
}
void productsDataGrid_Drop(object sender, DragEventArgs e)
{
if (rowIndex < 0)
return;
int index = this.GetCurrentRowIndex(e.GetPosition);
if (index < 0)
return;
if (index == rowIndex)
return;
if (index == productsDataGrid.Items.Count - 1)
{
MessageBox.Show("This row-index cannot be drop");
return;
}
ProductCollection productCollection = Resources["ProductList"] as ProductCollection;
Product changedProduct = productCollection[rowIndex];
productCollection.RemoveAt(rowIndex);
productCollection.Insert(index, changedProduct);
}
void productsDataGrid_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
rowIndex = GetCurrentRowIndex(e.GetPosition);
if (rowIndex < 0)
return;
productsDataGrid.SelectedIndex = rowIndex;
Product selectedEmp = productsDataGrid.Items[rowIndex] as Product;
if (selectedEmp == null)
return;
DragDropEffects dragdropeffects = DragDropEffects.Move;
if (DragDrop.DoDragDrop(productsDataGrid, selectedEmp, dragdropeffects)
!= DragDropEffects.None)
{
productsDataGrid.SelectedItem = selectedEmp;
}
}
private bool GetMouseTargetRow(Visual theTarget, GetPosition position)
{
Rect rect = VisualTreeHelper.GetDescendantBounds(theTarget);
Point point = position((IInputElement)theTarget);
return rect.Contains(point);
}
private DataGridRow GetRowItem(int index)
{
if (productsDataGrid.ItemContainerGenerator.Status
!= GeneratorStatus.ContainersGenerated)
return null;
return productsDataGrid.ItemContainerGenerator.ContainerFromIndex(index)
as DataGridRow;
}
private int GetCurrentRowIndex(GetPosition pos)
{
int curIndex = -1;
for (int i = 0; i < productsDataGrid.Items.Count; i++)
{
DataGridRow itm = GetRowItem(i);
if (GetMouseTargetRow(itm, pos))
{
curIndex = i;
break;
}
}
return curIndex;
}
}
}
视图模型文件
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections.ObjectModel;
namespace WpfApplication1
{
public class Product
{
public int ProductId { get; set; }
public string ProductName { get; set; }
public string ProductPrice { get; set; }
public bool IsActive { get; set; }
}
public class ProductCollection : ObservableCollection<Product>
{
public ProductCollection()
{
Add(new Product() { ProductId = 111, ProductName = "Books", ProductPrice = "500$" ,IsActive=true});
Add(new Product() { ProductId = 222, ProductName = "Cameras", ProductPrice = "600$", IsActive = true });
Add(new Product() { ProductId = 333, ProductName = "Cell Phones", ProductPrice = "700$", IsActive = true });
Add(new Product() { ProductId = 444, ProductName = "Clothing", ProductPrice = "800$", IsActive = true });
Add(new Product() { ProductId = 555, ProductName = "Shoes", ProductPrice = "900$", IsActive = true });
Add(new Product() { ProductId = 666, ProductName = "Gift Cards", ProductPrice = "500$", IsActive = true });
Add(new Product() { ProductId = 777, ProductName = "Crafts", ProductPrice = "400$", IsActive = true });
}
}
}
但是问题是在datagrid上实现了拖放功能后,我无法选中或取消选中任何复选框.
当我左键单击复选框时,将触发PreviewMouseLeftButtonDown事件.
如果要检查,请删除除以下以外的所有代码
public MainWindow()
{
InitializeComponent();
}
所以我想从PreviewMouseLeftButtonDown事件中删除该列.我在互联网上搜索了很多,但没有找到任何帮助.
任何帮助或建议都是可取的.
解决方法:
您可以使用一个辅助方法来确定MouseButtonEventArgs.OriginalSource是否是CheckBox的子元素:
void productsDataGrid_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
CheckBox checkBox = FindParent<CheckBox>(e.OriginalSource as DependencyObject);
if (checkBox == null)
{
rowIndex = GetCurrentRowIndex(e.GetPosition);
if (rowIndex < 0)
return;
productsDataGrid.SelectedIndex = rowIndex;
Product selectedEmp = productsDataGrid.Items[rowIndex] as Product;
if (selectedEmp == null)
return;
DragDropEffects dragdropeffects = DragDropEffects.Move;
if (DragDrop.DoDragDrop(productsDataGrid, selectedEmp, dragdropeffects)
!= DragDropEffects.None)
{
productsDataGrid.SelectedItem = selectedEmp;
}
}
}
static T FindParent<T>(DependencyObject dependencyObject) where T : DependencyObject
{
var parent = VisualTreeHelper.GetParent(dependencyObject);
if (parent == null)
return null;
var parentT = parent as T;
return parentT ?? FindParent<T>(parent);
}