Для вашей первой проблемы:
Вы должны обрабатывать случай, когда ваша кнопка нажата, но не перемещена. Я думаю, что лучшим способом сделать это (вместо задержки в 100 мс) было бы указать минимальный порог движения, выше которого начнется перетаскивание.
Вы можете сделать это так:
private const double _dragThreshold = 1.0;
private bool _dragging;
private Point startpos;
CancellationTokenSource cancellation;
private void Button_PreviewMouseMove(object sender, MouseEventArgs e)
{
var currentpos = e.GetPosition(this);
var delta = currentpos - startpos;
if ((delta.Length > _dragThreshold || _dragging) && e.LeftButton == MouseButtonState.Pressed)
{
_dragging = true;
Left += currentpos.X - startpos.X;
Top += currentpos.Y - startpos.Y;
}
}
private async void Button_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
if (e.ChangedButton != MouseButton.Left)
return;
_dragging = false;
startpos = e.GetPosition(this);
cancellation?.Cancel();
cancellation = new CancellationTokenSource();
}
Для вашей второй проблемы: кнопка будет захватывать мышь при событии мыши вниз.
Вам нужно отпустить захваченную мышь методом ReleaseMouseCapture
, когда вы закончите перетаскиванием.
private void Button_PreviewMouseUp(object sender, MouseButtonEventArgs e)
{
if (_dragging)
{
_dragging = false;
e.Handled = true;
var button = sender as Button;
button.ReleaseMouseCapture();
}
cancellation?.Cancel();
}