Frage

Ich muss in der Lage, die Doppelklick auf und Klick Ereignis auf dem WPF Stackpanel zu behandeln. Aber es gibt nicht so etwas wie den Doubleclick-Ereignis des Stackpanel. Ich möchte zwei verschiedene Operationen in diesen 2 Eventhandler tun.

Jede Idee, wie das zu tun?

Danke

War es hilfreich?

Lösung

Der beste Weg ist, Ihre eigene Maustaste Handler mit einem Timeout nach rechts - wenn das Ereignis innerhalb der Timeout-Zeit wieder ausgelöst wird, dann feuern Sie Ihre Nachricht doppelklicken, rufen Sie sonst die einzelnen Klick-Handler. Hier ist ein Beispielcode ( Edit: ursprünglich gefunden hier ):

/// <summary>
/// For double clicks
/// </summary>
public class MouseClickManager {
    private event MouseButtonEventHandler _click;
    private event MouseButtonEventHandler _doubleClick;

    public event MouseButtonEventHandler Click {
        add { _click += value; }
        remove { _click -= value; }
    }

    public event MouseButtonEventHandler DoubleClick {
        add { _doubleClick += value; }
        remove { _doubleClick -= value; }
    }

    /// <summary>
    /// Gets or sets a value indicating whether this <see cref="MouseClickManager"/> is clicked.
    /// </summary>
    /// <value><c>true</c> if clicked; otherwise, <c>false</c>.</value>
    private bool Clicked { get; set; }

    /// <summary>
    /// Gets or sets the timeout.
    /// </summary>
    /// <value>The timeout.</value>
    public int DoubleClickTimeout { get; set; }

    /// <summary>
    /// Initializes a new instance of the <see cref="MouseClickManager"/> class.
    /// </summary>
    /// <param name="control">The control.</param>
    public MouseClickManager(int doubleClickTimeout) {
        this.Clicked = false;
        this.DoubleClickTimeout = doubleClickTimeout;
    }

    /// <summary>
    /// Handles the click.
    /// </summary>
    /// <param name="sender">The sender.</param>
    /// <param name="e">The <see cref="System.Windows.Input.MouseButtonEventArgs"/> instance containing the event data.</param>
    public void HandleClick(object sender, MouseButtonEventArgs e) {
        lock (this) {
            if (this.Clicked) {
                this.Clicked = false;
                OnDoubleClick(sender, e);
            }
            else {
                this.Clicked = true;
                ParameterizedThreadStart threadStart = new ParameterizedThreadStart(ResetThread);
                Thread thread = new Thread(threadStart);
                thread.Start(e);
            }
        }
    }

    /// <summary>
    /// Resets the thread.
    /// </summary>
    /// <param name="state">The state.</param>
    private void ResetThread(object state) {
        Thread.Sleep(this.DoubleClickTimeout);

        lock (this) {
            if (this.Clicked) {
                this.Clicked = false;
                OnClick(this, (MouseButtonEventArgs)state);
            }
        }
    }

    /// <summary>
    /// Called when [click].
    /// </summary>
    /// <param name="sender">The sender.</param>
    /// <param name="e">The <see cref="System.Windows.Input.MouseButtonEventArgs"/> instance containing the event data.</param>
    private void OnClick(object sender, MouseButtonEventArgs e) {
        if (_click != null) {
            if (sender is Control) {
                (sender as Control).Dispatcher.BeginInvoke(_click, sender, e);
            }
        }
    }

    /// <summary>
    /// Called when [double click].
    /// </summary>
    /// <param name="sender">The sender.</param>
    /// <param name="e">The <see cref="System.Windows.Input.MouseButtonEventArgs"/> instance containing the event data.</param>
    private void OnDoubleClick(object sender, MouseButtonEventArgs e) {
        if (_doubleClick != null) {
            _doubleClick(sender, e);
        }
    }
}

Dann wird in der Steuerung wollen Sie die Ereignisse erhalten:

MouseClickManager fMouseManager = new MouseClickManager(200);
fMouseManager.Click += new MouseButtonEventHandler(YourControl_Click); 
fMouseManager.DoubleClick += new MouseButtonEventHandler(YourControl_DoubleClick);

Andere Tipps

 <StackPanel MouseDown="StackPanel_MouseDown">
   <!--stackpanel content-->
    <TextBlock>Hello</TextBlock>
</StackPanel>

Dann im Ereignishandler:

 private void StackPanel_MouseDown(object sender, MouseButtonEventArgs e)
    {
        if (e.ClickCount >= 2)
        { 
            string hello; //only hit here on double click  
        }
    }

Sollte funktionieren. Beachten Sie, dass einzelnen Klick in dem Stackpanel würde das Ereignis getroffen (aber nicht das, wenn check)

... Jahre später. @ Moomintroll-Lösung ist durchaus akzeptabel. Eine weitere Option ist die Stapelplatte in einer Inhaltskontrolle zu wickeln, die das Doppelklickereignis unterstützt.

<ContentControl MouseDoubleClick="DoubleClickHandler" >
    <StackPanel>

    </StackPanel>
</ContentControl>

Eine andere Möglichkeit ist es, ein Mousebinding zu den Inputbindings auf der StackElement hinzufügen und dann ein Command hinzufügen, die von Mousebinding aktiviert wird. Im Großen und Ganzen ist dies eine bessere Praxis als Mechanismen Ereignis basiert, weil sie die Speicherleck Probleme verursacht durch starke Referenzen vermeidet. Es bietet auch für die Trennung von Befehlslogik von der Darstellung.

Dass gesagt wird, es ist nicht so geradlinig und auf das Ereignis Anbringen macht für eine große Verknüpfung.

Und es versteht sich von selbst, machen Sie Ihre Stackpanel Hintergrund zumindest transparent oder es wird nicht durch den Mausklick getroffen Test gefangen werden, wenn Sie auf „Hintergrund“ klicken. Null Hintergründe werden durch die Treffererkennung übersprungen.

Ich hatte ein ähnliches Problem (antworten einziges Click-Ereignis und machen eine zusätzliche Arbeit bei Doppelklick Ereignisse). Ich löste das Problem auf diese Weise:

1) definieren und eine ganze Zahl deklarieren letzten Klick Zeitstempel halten

int lastClickTimestamp;

2) in Window_Loaded Methode Initialize zuvor deklarierte Variable mit irgendeiner Zahl größer als 200

lastClickTimestamp = 1000;

3) Maustaste Handler zu Ihrem Stack Panel hinzufügen

stackPanel.MouseLeftButtonUp += new MouseButtonEventHandler(stackPanel_MouseLeftButtonUp);

4) fügen Sie folgende Methode

void stackPanel_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        if (e.Timestamp - lastClickTimeStamp < 200)
        {
            //double click
        }
        lastClickTimeStamp = e.Timestamp;

        //single click
    }

Dieser Code ist nutzlos, wenn Sie separat müssen Klick und Doppelklick-Ereignis erfassen. Diese Situation führt etwas mehr Komplexität, aber auf jeden Fall gelöst werden kann.

Komplette Antwort mit WPF DispatcherTimer. Wir schaffen den Timer auf die Nachfrage und es trennen, wenn geschieht, um Ressourcen Verstopfen zu verhindern.

Die C #:

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Input;
using System.Windows.Threading;

public partial class MainWindow : Window
{
    DispatcherTimer dt;

    bool clear_timer()
    {
        if (dt == null)
            return false;
        dt.Tick -= _single_click;
        dt = null;
        return true;
    }

    private void _click(Object sender, MouseButtonEventArgs e)
    {
        if (clear_timer())
            Debug.Print("double click");
        else
            dt = new DispatcherTimer(
                        TimeSpan.FromMilliseconds(GetDoubleClickTime()),
                        DispatcherPriority.Normal,
                        _single_click,
                        Dispatcher);
    }

    void _single_click(Object sender, EventArgs e)
    {
        clear_timer();
        Debug.Print("single click");
    }

    public MainWindow() { InitializeComponent(); }

    [DllImport("user32.dll")]
    static extern uint GetDoubleClickTime();
 };

Die XAML:

<Window x:Class="MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <StackPanel Orientation="Horizontal"
                Background="AliceBlue"
                Width="100"
                Height="100"
                MouseLeftButtonDown="_click" />
</Window>

Es gibt eine einfachere Lösung, dies zu tun.

In Stackpanel Veranstaltung PreviewMouseLeftDown (zum Beispiel), können Sie überprüfen, ob MouseButtonEventArgs.ClickCount Eigenschaft einen Wert von 2 hat. 1 = Mit einem Klick 2 = Double Click

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top