سؤال

أنا بحاجة إلى أن تكون قادرة على التعامل مع انقر نقرا مزدوجا فوق و بنقرة واحدة الحدث على WPF StackPanel.ولكن لا يوجد شيء مثل StackPanel دبل كليك الحدث.أريد أن أفعل 2 عمليات مختلفة في هذه 2 EventHandlers.

أي فكرة عن كيفية فعل ذلك ؟

شكرا لك

هل كانت مفيدة؟

المحلول

فإن أفضل طريقة هي أن الحق الخاص بك زر الماوس معالج مع مهلة - إذا كان الحدث هو النار مرة أخرى خلال فترة المهلة ، ثم النار الخاص بك doubleclick الرسالة ، وإلا استدعاء واحد انقر فوق معالج.هنا بعض التعليمات البرمجية (تحرير: وجدت أصلا هنا):

/// <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);
        }
    }
}

ثم في السيطرة تريد أن تلقي الأحداث:

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

نصائح أخرى

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

ثم في معالج الحدث:

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

يجب أن تعمل.علما بأن واحدة عن طريق النقر في StackPanel ضرب الحدث (ولكن تفشل إذا تحقق)

...سنوات في وقت لاحق.@MoominTroll حل مقبول تماما.وثمة خيار آخر هو التفاف كومة الفريق في السيطرة على المحتوى الذي يدعم انقر نقرا مزدوجا فوق الحدث.

<ContentControl MouseDoubleClick="DoubleClickHandler" >
    <StackPanel>

    </StackPanel>
</ContentControl>

وثمة خيار آخر هو إضافة MouseBinding إلى InputBindings على StackElement ثم إضافة CommandBinding أن يحصل على تفعيلها من خلال MouseBinding.على العموم هذا هو أفضل ممارسة من الحدث آليات لأنه يتجنب حدوث تسرب للذاكرة القضايا الناجمة عن إشارات قوية.كما ينص على الفصل بين الأوامر المنطق من التمثيل.

أن يقال ، وليس على التوالي إلى الأمام و ربط الحدث يجعل اختصار كبير.

وغني عن القول, جعل الخاص بك stackpanel الخلفية على الأقل شفافة أو أنها لن تكون اشتعلت من قبل الماوس انقر ضرب الاختبار عندما كنت انقر على "خلفية".Null الخلفيات تخطي من خلال ضرب الكشف.

كان لي مشكلة مماثلة (الرد على واحد انقر فوق الحدث والقيام بأعمال إضافية في حالة انقر نقرا مزدوجا فوق الحدث).أنا حل المشكلة بهذه الطريقة:

1) تحدد وتعلن بعض صحيح لعقد اخر انقر الزمني

int lastClickTimestamp;

2) في Window_Loaded طريقة تهيئة أعلن سابقا متغير مع بعض أكبر عدد من 200

lastClickTimestamp = 1000;

3) إضافة زر الماوس معالج الخاص بك كومة الفريق

stackPanel.MouseLeftButtonUp += new MouseButtonEventHandler(stackPanel_MouseLeftButtonUp);

4) إضافة الطريقة التالية

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

        //single click
    }

هذا الرمز هو عديمة الفائدة إذا كنت تحتاج إلى بشكل منفصل كشف واحد انقر فوق ثم انقر نقرا مزدوجا فوق الحدث.هذا الوضع يدخل قليلا أكثر تعقيد, ولكن بالتأكيد يمكن حلها.

إجابة كاملة باستخدام WPF DispatcherTimer.ونحن إنشاء جهاز ضبط الوقت على الطلب قطع الاتصال عندما يتم ذلك من أجل منع الموارد انسداد.

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();
 };

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>

هناك حل أسهل أن تفعل هذا.

في StackPanel الحدث PreviewMouseLeftDown (على سبيل المثال) ، يمكنك التحقق من إذا MouseButtonEventArgs.ClickCount الخاصية قيمة 2.1 = بنقرة واحدة 2 = انقر نقرا مزدوجا فوق

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top