Как предотвратить «перетаскивание» себя в таблицу данных?

StackOverflow https://stackoverflow.com/questions/614404

Вопрос

Я реализую функцию перетаскивания между двумя представлениями данных. Это работает, как и предполагалось, с одним исключением: возможно перетаскивание в пределах одной и той же сетки данных. Это приводит к дублированию строк. Я хочу ограничить функциональность, чтобы я мог перетаскивать только одно представление данных в другое. Кто-нибудь знает, как этого можно достичь? Я предполагаю, что требуется какой-то тест на попадание, но я не уверен, как это реализовать ...

Я использую следующий код:

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;

Карлос Мериге

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top