لماذا لا ينقر الزر على حدث "Bubble Up Visual Tree" إلى StackPanel كما تنص مقالة MSDN؟

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

  •  20-08-2019
  •  | 
  •  

سؤال

في مقالة MSDN فهم الأحداث والأوامر الموجهة في WPF, ، فإنه ينص

سيتم فقاعة الحدث (الانتشار) أعلى الشجرة المرئية من العنصر المصدر حتى يتم التعامل معها أو تصل إلى عنصر الجذر.

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

لما لا؟ ماذا يعنيون بعد ذلك عن طريق "الفقاعات" إذا لم يكن هذا؟

XAML:

<Window x:Class="TestClickEvents456.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">
    <StackPanel x:Name="TheStackPanel"
                Background="Yellow"
                MouseDown="TheStackPanel_MouseDown">
        <Button x:Name="TheButton"
                Margin="10"
                Content="Click This"/>
        <TextBlock x:Name="TheMessage"
                   Text="Click the button or the yellow area"/>
    </StackPanel>
</Window>

الكود-بيهيند:

using System.Windows;
using System.Windows.Input;

namespace TestClickEvents456
{
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
        }

        private void TheStackPanel_MouseDown(object sender, MouseButtonEventArgs e)
        {
            TheMessage.Text = "StackPanel was clicked.";
        }

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

المحلول

فقاعات الحدث ، حتى يتم التعامل معها ...

نظرًا لأن الزر يقوم بشيء بنقرات الماوس الخاصة بك ، فإنه يمتص حدث الماوس الخاص بك ويحوله إلى clickevent.

إذا كنت تستخدم المعاينة ، فسترى أن StackPanel يتلقى الحدث أولاً قبل الزر .. معاينة الأحداث استخدم نهج النفق لأسفل ..

نصائح أخرى

كما قال آخرون ، فذلك لأن MouseDown يتم التعامل مع الحدث من قبل Button قبل أن يتم فقاعاتها أكثر. يمكنك رؤية هذا في العاكس ، في ButtonBase.OnMouseLeftButtonDown:

protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
{
    if (this.ClickMode != ClickMode.Hover)
    {
        e.Handled = true;
        // SNIP...
    }
    base.OnMouseLeftButtonDown(e);
}

حل واحد هو الاستماع إلى أ MouseDown الحدث ، وتشير إلى أنك لا تهتم إذا تمت معالجة الحدث. يمكنك القيام بذلك مع AddHandler طريقة. إنه يحتوي على تحميل منطقي يتيح لك الاستماع للأحداث التي تم التعامل معها بالفعل.

إذا قمت بذلك في مكان ما بدلاً من ضبط معالج Mousedown في XAML:

TheStackPanel.AddHandler(MouseDownEvent, new MouseButtonEventHandler(TheStackPanel_MouseDown), true);

سوف تتلقى كل شيء MouseDown الأحداث على TheStackPanel, ، بغض النظر عما إذا كانت قد تم التعامل معها.

بالإضافة إلى ذلك ، إذا كنت تريد أن يتلقى StackPanel الحدث ، فقم بتغيير Stackpanel Xaml إلى:

<StackPanel x:Name="TheStackPanel" 
            Background="Yellow"
            Button.Click="TheStackPanel_MouseDown" />

وتوقيع الحدث إلى:

private void TheStackPanel_MouseDown(object sender, RoutedEventArgs e)

في هذه الحالة ، سيتلقى StackPanel حدث النقر فوق الزر. ومع ذلك ، فإن النقر على stackpanel نفسه لن يطلق أي حدث ، لأنه يستمع على وجه التحديد إلى زر النقر.

ذلك لأنه يتم التقاط جميع الرسائل تم التعامل معها حسب الزر وتتوقف الرسائل تتوقف الرسالة الفقاعات هناك. الجواب صحيح في نص سؤالك:

سيقوم الحدث بفقاعة (انتشار) على الشجرة المرئية من عنصر المصدر حتى يتم التعامل معها أو يصل إلى عنصر الجذر.

تعديل:

علق إدوارد تانغاي (OP) على هذه الإجابة وأنا أقوم بنسخ تعليقه هنا لأنه مناسب جدًا:

"لا أرى أن الزر يتعامل مع الحدث ، أي ليس لدي أي معالج نقرة على الزر ، ولدي معالج نقرة (mousedown) على stackpanel ، وبالتالي أعتقد أنه سيخترق الزر منذ الزر لا يتعامل معها ويتم التعامل معها من قبل stackpanel أي ، أليس كذلك؟ "

أنت محق. لا يتعامل الزر مع حدث Mousedown لأنه لم يتم تحديد أي معالج له في هذا التحكم.

ولكن ، إذن ، فإن موسى هو خاص بطريقة ما. على الأقل في نماذج Windows ، يتم استخدامه لبدء الإجراءات كرسوم وسحب ذلك ، عندما يحصل عنصر التحكم على الحدث ، فإنه يستمر في فخ جميع رسائل الماوس اللاحقة حتى لو لم تكن قد حددت معالجاتها. يتم إجراء هذا الفخ عندما يقوم التحكم بتعيين خاصية التقاط إلى True ، وهذا يوقف الأحداث اللاحقة بشكل فعال. يتم تعيين خاصية الالتقاط مرة أخرى إلى False بواسطة Windows Forms عندما تحصل على حدث ماوس.

أكرر ، هذه هي الطريقة التي تعمل بها في نماذج Windows ، قد ترغب في التحقق من هذا ، ولكن ، لا يوجد سبب لوجود هذا مختلف بالنسبة لـ WPF.

للإشارة: Se القسم "معالجة نماذج Windows" في http://blogs.msdn.com/jfoscoding/archive/2005/07/28/44647.aspx (قم بالتمرير قليلاً من منتصف الصفحة).

ملاحظة: راجع تعليقي على إجابة Arcturu للحصول على مرجع على أحداث الفقاعة والنفقات تثير التسلسلات.

زر القمع قمع Mousedown و Mouseup لأن الحدث الزر هو حدث عالي المستوى ولديه جزء من التعليمات البرمجية التي تمنح مقبض العلم هذا السبب القمع لموسدودون لحل هذه المشكلة يمكنك إضافة هذا الرمز في مُنشئ النافذة

TheButton.AddHandler(
    UIElement.MouseDownEvent, 
    new MouseButtonEventHandler(TheStackPanel_MouseDown),
    true);
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top