Как предотвратить «перетаскивание» себя в таблицу данных?
-
03-07-2019 - |
Вопрос
Я реализую функцию перетаскивания между двумя представлениями данных. Это работает, как и предполагалось, с одним исключением: возможно перетаскивание в пределах одной и той же сетки данных. Это приводит к дублированию строк. Я хочу ограничить функциональность, чтобы я мог перетаскивать только одно представление данных в другое. Кто-нибудь знает, как этого можно достичь? Я предполагаю, что требуется какой-то тест на попадание, но я не уверен, как это реализовать ...
Я использую следующий код:
Private Sub dgvFMAvailable_MouseMove(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles dgvFMAvailable.MouseMove
If e.Button = Windows.Forms.MouseButtons.Left Then
Me.dgvFMAvailable.DoDragDrop(Me.dgvFMAvailable.SelectedRows, DragDropEffects.Move)
End If
End Sub
и
Private Sub dgvFMSelected_DragDrop(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles dgvFMSelected.DragDrop
Try
Me.SelectFM(CType(e.Data.GetData(GetType(DataGridViewSelectedRowCollection)), DataGridViewSelectedRowCollection))
Finally
e.Effect = DragDropEffects.None
End Try
End Sub
Решение
Просто быстрая идея. Что если при запуске перетаскивания вы держите имя исходной сетки. Когда вы выполняете удаление, проверьте имя, если это один и тот же объект, не разрешайте удаление.
Другие советы
Просто проверьте равенство ссылок при отбрасывании. Примерно так:
If Object.ReferenceEquals(droppedThing, thingWhereItWasDropped)
' Don't drop it
Else
' Drop it
End If
Я не смог найти хорошего ответа на это, хотя, похоже, это часто встречающаяся проблема. Поэтому я использовал ответ Гбианки следующим образом:
public bool DraggingFromFileLinkDGV { get; set; }
void grdFiles_MouseDown(object sender, MouseEventArgs e)
{
this.DraggingFromFileLinkDGV = true;
}
void grdFiles_MouseLeave(object sender, EventArgs e)
{
this.DraggingFromFileLinkDGV = false;
}
void grdFiles_DragDrop(object sender, DragEventArgs e)
{
// Avoid DragDrop's on jittery DoubleClicks
if (this.DraggingFromFileLinkDGV) return;
// Your DragDrop code here ...
}
Теперь я действительно сделал это специально для предотвращения " блуждания " двойной щелчок, где мышь немного перемещается между двойным щелчком. Это предотвращает двойные щелчки, регистрирующиеся как перетаскиваемые объекты, а также отвечает на вопрос ОП.
Имейте в виду, это не работает 100% времени. По-видимому, некоторые события являются "потерянными" в 1 из 20 случаев. Я не определил, что именно меняется в тех ситуациях, когда он регистрирует каплю на себя. В случае предотвращения двойного щелчка, регистрируемого как перетаскивание, 95% достаточно, потому что он только что был установлен, чтобы избежать раздражения. Если вам нужно что-то, что на 100% эффективно, вам, возможно, придется попробовать что-то другое или выяснить, почему это не работает в этих нескольких случаях.
Один из способов - сохранить строковое описание того, что вы перетаскиваете, в DataObject, когда вы начинаете перетаскивать, то есть:
Dim dataObj As New DataObject
...
dataObj.SetText(G_SELF_DRAG_DROP_FLAG)
Затем в DragEnter проверьте, есть ли флаг:
Public Sub ProcessAttachment_DragEnter(ByRef e As System.Windows.Forms.DragEventArgs)
' prevent dragging onto self
Dim s = e.Data.GetData(DataFormats.Text)
If s IsNot Nothing Then
If s.contains(G_SELF_DRAG_DROP_FLAG) Then
e.Effect = DragDropEffects.None
Exit Sub
End If
End If
...
End Sub
Установка флага в false в событии MouseLeave
не сработала правильно для меня. MouseLeave
продолжал вызываться, как только я вызвал DoDragDrop
. Р>
Наконец-то я понял, как это работает:
A) I create a private bool DraggingFromHere flag
B) Right before calling DoDragDrop, I set this.DraggingFromHere = true
C) In the MouseUp event, I set this.DraggingFromHere = false
D) In the DragDro event, I simply to this:
if(this.DraggingFromHere) return;
Карлос Мериге