次のようにTextBlockでシングルクリックをキャッチできます。
private void TextBlock_MouseDown(object sender, MouseButtonEventArgs e)
{
MessageBox.Show("you single-clicked");
}
次のようにTextBlockでダブルクリックをキャッチできます:
private void TextBlock_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
if (e.ClickCount == 2)
{
MessageBox.Show("you double-clicked");
}
}
}
しかし、1つのTextBlockで両方をキャッチし、2つを区別するにはどうすればよいですか?
クリックシーケンスが終了した後にイベントを発生させる必要があります...それはいつですか?タイマーを使うことをお勧めします。 MouseDownイベントはそれをリセットし、クリック数を増やします。タイマー間隔が経過すると、クリック数を評価するための呼び出しが行われます。
private System.Timers.Timer ClickTimer;
private int ClickCounter;
public MyView()
{
ClickTimer = new Timer(300);
ClickTimer.Elapsed += new ElapsedEventHandler(EvaluateClicks);
InitializeComponent();
}
private void TextBlock_MouseDown(object sender, MouseButtonEventArgs e)
{
ClickTimer.Stop();
ClickCounter++;
ClickTimer.Start();
}
private void EvaluateClicks(object source, ElapsedEventArgs e)
{
ClickTimer.Stop();
// Evaluate ClickCounter here
ClickCounter = 0;
}
乾杯!
違いを検出する必要がある場合は、Label
などのコントロールを使用することをお勧めします。
label.MouseDown += delegate(object sender, MouseEventArgs e)
{
if (e.ClickCount == 1)
{
// single click
}
};
label.MouseDoubleClick += delegate
{
// double click
};
編集:私のアドバイスはMSDNのドキュメントからのものでした:
Controlクラスは、PreviewMouseDoubleClickイベントとMouseDoubleClickイベントを定義しますが、対応するシングルクリックイベントは定義しません。ユーザーがコントロールを1回クリックしたかどうかを確認するには、MouseDownイベント(または対応するイベントの1つ)を処理し、ClickCountプロパティ値が1であるかどうかを確認します。
ただし、そうすると、ユーザーがシングルクリックした場合でもシングルクリック通知が表示されます。
2つを区別するには、タイマーを使用する必要があります。 GUIでフォームにタイマーを追加します(その方法で最も簡単です-自動的に破棄などを処理します...)。私の例では、タイマーはclickTimer
と呼ばれています。
private bool mSingleClick;
private void TextBlock_MouseUp(object sender, MouseButtonEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
if (e.ClickCount < 2)
{
mSingleClick = true;
clickTimer.Interval = System.Windows.Forms.SystemInformation.DoubleClickTime;
clickTimer.Start();
}
else if (e.ClickCount == 2)
{
clickTimer.Stop();
mSingleClick = false;
MessageBox.Show("you double-clicked");
}
}
}
private void clickTimer_Tick(object sender, EventArgs e)
{
if (mSingleClick)
{
clickTimer.Stop();
mSingleClick = false;
MessageBox.Show("you single-clicked");
}
}
次のように、MouseDown
イベントを使用してクリック数をカウントするだけです。
if (e.ChangedButton == MouseButton.Left && e.ClickCount == 2)
{
// your code here
}
私はこのようにそれをしました、そしてそれは完全に働きます
If e.Clicks = 2 Then
doubleClickTimer.Stop()
ElseIf e.Clicks = 1 Then
doubleClickTimer.Enabled = True
doubleClickTimer.Interval = 1000
doubleClickTimer.Start()
End If
Private Sub doubleClickTimer_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles doubleClickTimer.Tick
OpenWebPage("abc")
doubleClickTimer.Stop()
End Sub
それは私の実用的な解決策です:)
#region message label click --------------------------------------------------------------------------
private Timer messageLabelClickTimer = null;
private void messageLabel_MouseUp(object sender, MouseButtonEventArgs e)
{
Debug.Print(e.ChangedButton.ToString() + " / Left:" + e.LeftButton.ToString() + " Right:" + e.RightButton.ToString() + " click: " + e.ClickCount.ToString());
// in MouseUp (e.ClickCount == 2) don't work!! Always 1 comes.
// in MouseDown is set e.ClickCount succesfully (but I don't know should I fire one clicked event or wait second click)
if (e.ChangedButton == MouseButton.Left)
{
if (messageLabelClickTimer == null)
{
messageLabelClickTimer = new Timer();
messageLabelClickTimer.Interval = 300;
messageLabelClickTimer.Elapsed += new ElapsedEventHandler(messageLabelClickTimer_Tick);
}
if (! messageLabelClickTimer.Enabled)
{ // Equal: (e.ClickCount == 1)
messageLabelClickTimer.Start();
}
else
{ // Equal: (e.ClickCount == 2)
messageLabelClickTimer.Stop();
var player = new SoundPlayer(ExtraResource.bip_3short); // Double clicked signal
player.Play();
}
}
}
private void messageLabelClickTimer_Tick(object sender, EventArgs e)
{ // single-clicked
messageLabelClickTimer.Stop();
var player = new SoundPlayer(ExtraResource.bip_1short); // Single clicked signal
player.Play();
}
#endregion
私の問題は、DataGrid
のWPF
の行をシングル/ダブルクリックすることでした。何らかの理由で、ButtonDown
イベントが発生せず、OnMouseLeftButtonUp
イベントのみが発生しました。とにかく、私はシングルクリックをダブルクリックとは異なる方法で処理したかったのです。以下に問題が解決するまで問題を抽出するのに少し時間がかかります(解決策は完璧ではないと思いますが、うまくいくようです)。 Task
を呼び出すAction
を作成しました。そのAction
のターゲットは2回目のクリックで更新できます。これが誰かを助けることを願っています!
private Action _clickAction;
private int _clickCount;
private void Grid_OnMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
Debug.WriteLine("Button Click Occurred");
_clickCount++;
if (_clickCount == 1)
{
_clickAction = SingleClick;
}
if (_clickCount > 1)
{
_clickAction = DoubleClick;
}
if (_clickCount == 1)
{
Task.Delay(200)
.ContinueWith(t => _clickAction(), TaskScheduler.FromCurrentSynchronizationContext())
.ContinueWith(t => { _clickCount = 0; });
}
}
private void DoubleGridClick()
{
Debug.WriteLine("Double Click");
}
private void SingleGridClick()
{
Debug.WriteLine("Single Click");
}
MouseDownの代わりにMouseUpでそれを行うことができます。そうすれば、ClickCount
プロパティにクリックの総数を尋ね、その時点から何をするかを決めることができます。
私の提案は、単にUserControl
を使用してTask
に実装されています。
private int _clickCount = 0;
protected override void OnPreviewMouseDown(MouseButtonEventArgs e)
{
_clickCount = e.ClickCount;
}
protected override async void OnPreviewMouseUp(MouseButtonEventArgs e)
{
if (_clickCount > 1)
{
//apparently a second mouse down event has fired => this must be the second mouse up event
//no need to start another task
//the first mouse up event will be handled after the task below
return;
}
await Task.Delay(500);
if (_clickCount == 1)
{
//single click
}
else
{
//double (or more) click
}
}
もちろん、これらすべてのソリューションの欠点は、ユーザーのアクションに実際に応答するまでに遅延が発生することです。