c#-在WPF中实现拖放后,无法从网格列中选中或取消选中复选框

在我的项目中,我遇到一种情况,需要在数据网格的行上进行拖放.在数据网格中,我有一列用于选择或取消选择特定项目的复选框.

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);
}
上一篇:EasyUI常用操作


下一篇:C#-从匿名对象获取值