Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/276.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# WPF保持鼠标按钮通风孔向下_C#_Wpf_Xaml - Fatal编程技术网

C# WPF保持鼠标按钮通风孔向下

C# WPF保持鼠标按钮通风孔向下,c#,wpf,xaml,C#,Wpf,Xaml,我有一个数据网格,在其中我使用DragAndDropBehavior向上/向下移动项目: public class DataGridRowDragAndDropBehavior { public delegate Point GetPosition(IInputElement element); int rowIndex = -1; public static DependencyProperty DataGridDr

我有一个数据网格,在其中我使用DragAndDropBehavior向上/向下移动项目:

public class DataGridRowDragAndDropBehavior
    {    
        public  delegate  Point GetPosition(IInputElement element);


        int   rowIndex = -1;

        public static DependencyProperty DataGridDragAndDropEnabled =
            DependencyProperty.RegisterAttached("DataGridDragAndDropEnabled", typeof(bool),
                typeof(DataGridRowDragAndDropBehavior), new UIPropertyMetadata(false, OnDataGridDragAndDropEnabled));

        private static void OnDataGridDragAndDropEnabled(object sender, DependencyPropertyChangedEventArgs e)
        {
            var dataGrid = (DataGrid) sender;
          dataGrid.PreviewMouseLeftButtonDown += Instance.productsDataGrid_PreviewMouseLeftButtonDown;
           dataGrid.Drop +=Instance.productsDataGrid_Drop;

        }

        public static bool GetDataGridDragAndDropEnabled(DependencyObject obj)
        {
            return (bool) obj.GetValue(DataGridDragAndDropEnabled);
        }
        public static void SetDataGridDragAndDropEnabled(DependencyObject obj, bool value)
        {
            obj.SetValue(DataGridDragAndDropEnabled, value);
        }


        private static DataGridRowDragAndDropBehavior instance = new DataGridRowDragAndDropBehavior();

        public static DataGridRowDragAndDropBehavior Instance
        {
            get { return instance; }
            set { instance = value; }
        }

         void productsDataGrid_Drop(object sender, DragEventArgs e)
         {

             var dataGrid = (DataGrid) sender;
             var dataGridSource = (System.Collections.IList)dataGrid.ItemsSource;

            if (rowIndex < 0)
                    return;
                var index = GetCurrentRowIndex(e.GetPosition,dataGrid);
                if (index < 0)
                    return;
                if (index == rowIndex)
                    return;
                //if (index == dataGrid.Items.Count - 1)
                //{
                //    MessageBox.Show("This row-index cannot be drop");
                //    return;
                //}

                var  changedItem = dataGridSource[rowIndex];
                dataGridSource.RemoveAt(rowIndex);
                dataGridSource.Insert(index, changedItem);


         }

         void   productsDataGrid_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
         {

             var dataGrid = (DataGrid) sender;

            rowIndex = GetCurrentRowIndex(e.GetPosition,dataGrid);
            if (rowIndex < 0)
                return;
            dataGrid.SelectedIndex = rowIndex;
            Register selectedEmp = dataGrid.Items[rowIndex] as Register;
            if (selectedEmp == null)
                return;
            DragDropEffects dragdropeffects = DragDropEffects.Move;
            if (DragDrop.DoDragDrop(dataGrid, selectedEmp, dragdropeffects)
                                != DragDropEffects.None)
            {
                dataGrid.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,DataGrid dataGrid)
        {
            if (dataGrid.ItemContainerGenerator.Status
                    != GeneratorStatus.ContainersGenerated)
                return null;
            return dataGrid.ItemContainerGenerator.ContainerFromIndex(index)
                                                            as DataGridRow;
        }

        private   int GetCurrentRowIndex(GetPosition pos,DataGrid dataGrid)
        {
            int curIndex = -1;
            for (int i = 0; i < dataGrid.Items.Count; i++)
            {
                DataGridRow itm = GetRowItem(i,dataGrid);
                if (GetMouseTargetRow(itm, pos))
                {
                    curIndex = i;
                    break;
                }
            }
            return curIndex;
        }
    }

一个更好的解决方案是使用
MouseMove
事件,并检查是否按下左键开始拖放:
e.LeftButton==MouseButtonState.pressed

但是,如果您希望像在注释中建议的那样使用
MouseDown
解决方案,那么您需要将事件冒泡并\或延迟DnD执行,因为这是进一步路由停止的原因

可能已经有了一些健壮的解决方案,但从我的头脑中,我们可以使用简单的计时器使其工作。为此,我们还需要
PreviewMouseLeftButtonUp

private static void OnDataGridDragAndDropEnabled(object sender, DependencyPropertyChangedEventArgs e)
{
    var dataGrid = (DataGrid)sender;
    dataGrid.PreviewMouseLeftButtonDown += Instance.productsDataGrid_PreviewMouseLeftButtonDown;
    dataGrid.PreviewMouseLeftButtonUp += Instance.productsDataGrid_PreviewMouseLeftButtonUp;
    dataGrid.Drop += Instance.productsDataGrid_Drop;
}
然后我们只需要以延迟(这里是400毫秒)启动它,以便所有控件都有时间响应。当鼠标按钮打开时,我们停止:

private System.Timers.Timer dragTimer;

void productsDataGrid_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
   var dataGrid = (DataGrid)sender;

   dragTimer = new System.Timers.Timer(400);
   System.Timers.ElapsedEventHandler elapsed = null;
   elapsed = (s, ee) =>
   {
      dragTimer.Elapsed -= elapsed;

      dataGrid.Dispatcher.Invoke(() =>
      {
         rowIndex = GetCurrentRowIndex(e.GetPosition, dataGrid);
         if (rowIndex < 0) return;

         dataGrid.SelectedIndex = rowIndex;
         object selectedEmp = dataGrid.Items[rowIndex];
         if (selectedEmp == null) return;

         DragDropEffects dragdropeffects = DragDropEffects.Move;
         if (DragDrop.DoDragDrop(dataGrid, selectedEmp, dragdropeffects)
               != DragDropEffects.None)
         {
            dataGrid.SelectedItem = selectedEmp;
         }
      });
   };

   dragTimer.Elapsed += elapsed;
   dragTimer.Start();
}

private void productsDataGrid_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
   if (dragTimer == null) return;

   dragTimer.Stop();
   dragTimer.Dispose();
   dragTimer = null;
}
private System.Timers.Timer dragTimer;
void productsDataGrid\u PreviewMouseLeftButtonDown(对象发送器,鼠标按钮Ventargs e)
{
var dataGrid=(dataGrid)发送方;
dragTimer=新系统定时器定时器定时器(400);
System.Timers.ElapsedEventHandler EXPERSED=null;
经过=(s,ee)=>
{
dragTimer.appeated-=已用;
dataGrid.Dispatcher.Invoke(()=>
{
rowIndex=GetCurrentRowIndex(例如GetPosition,dataGrid);
if(rowIndex<0)返回;
dataGrid.SelectedIndex=rowIndex;
objectselectedemp=dataGrid.Items[rowIndex];
if(selectedEmp==null)返回;
DragDropEffects DragDropEffects=DragDropEffects.Move;
if(DragDrop.DoDragDrop(数据网格,selectedEmp,dragdropeffects)
!=DragDropEffects。无)
{
dataGrid.SelectedItem=selectedEmp;
}
});
};
dragTimer.appeated+=已用时间;
dragTimer.Start();
}
私有void productsDataGrid\u预览鼠标左键(对象发送器,鼠标按钮Ventargs e)
{
if(dragTimer==null)返回;
dragTimer.Stop();
dragTimer.Dispose();
dragTimer=null;
}

有很多方法可以让它变得更好,但它应该是这样工作的。

这是一种奇怪的DnD方法,依赖MouseDown是混乱的。为什么不直接使用MouseMove并检查鼠标左键是否被按下(
e.LeftButton==MouseButtonState.pressed
)?你是对的。使用MouseMove事件也解决了我的问题:)。但是,如果我真的想使用MouseDown事件,您知道如何将其向下挖掘,以便它到达我的复选框吗?我不是说,您的答案是错误的,但这是一种“变通方法”。你知道如何让这件事成为泡泡吗?@KarolŻurowski,你不需要它来泡泡,你总是可以直接处理,而不依赖路由策略和谁来处理什么。
private static void OnDataGridDragAndDropEnabled(object sender, DependencyPropertyChangedEventArgs e)
{
    var dataGrid = (DataGrid)sender;
    dataGrid.PreviewMouseLeftButtonDown += Instance.productsDataGrid_PreviewMouseLeftButtonDown;
    dataGrid.PreviewMouseLeftButtonUp += Instance.productsDataGrid_PreviewMouseLeftButtonUp;
    dataGrid.Drop += Instance.productsDataGrid_Drop;
}
private System.Timers.Timer dragTimer;

void productsDataGrid_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
   var dataGrid = (DataGrid)sender;

   dragTimer = new System.Timers.Timer(400);
   System.Timers.ElapsedEventHandler elapsed = null;
   elapsed = (s, ee) =>
   {
      dragTimer.Elapsed -= elapsed;

      dataGrid.Dispatcher.Invoke(() =>
      {
         rowIndex = GetCurrentRowIndex(e.GetPosition, dataGrid);
         if (rowIndex < 0) return;

         dataGrid.SelectedIndex = rowIndex;
         object selectedEmp = dataGrid.Items[rowIndex];
         if (selectedEmp == null) return;

         DragDropEffects dragdropeffects = DragDropEffects.Move;
         if (DragDrop.DoDragDrop(dataGrid, selectedEmp, dragdropeffects)
               != DragDropEffects.None)
         {
            dataGrid.SelectedItem = selectedEmp;
         }
      });
   };

   dragTimer.Elapsed += elapsed;
   dragTimer.Start();
}

private void productsDataGrid_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
   if (dragTimer == null) return;

   dragTimer.Stop();
   dragTimer.Dispose();
   dragTimer = null;
}