【问题标题】:How does Mouse click raises a Button's event鼠标单击如何引发按钮事件
【发布时间】:2016-02-15 08:43:56
【问题描述】:

这里有两段代码,第一个 WPF,第二个是控制台应用程序

// This is a default Form1 class of a WPF application
// and I have added a button to the form.
partial class Form1
{
private void InitializeComponent()
{
    this.button1 = new System.Windows.Forms.Button();
    this.button1.Location = new System.Drawing.Point(62, 12);
    this.button1.Name = "button1";
    this.button1.Size = new System.Drawing.Size(75, 23);
    this.button1.TabIndex = 0;
    this.button1.Text = "Lloyd";
    this.button1.UseVisualStyleBackColor = true;
    this.button1.Click += new System.EventHandler(this.button1_Click);
} 

// here the buttons on the form are declared private
// how does the mouse click access the private button's event 
private System.Windows.Forms.Button button1;
}

这是一个控制台应用程序。 我在试验这个程序时感到困惑。 这里的 PublishingBall 类类似于 Button 类, 这个类有一个类似于 Click 事件的 Throw 事件。 在主要方法中,我试图复制鼠标点击 通过选择一些将调用 PublishingBall 事件的数字 但我只能访问 PublishingBall 事件,因为它们是在 FielderSubscriber 的类中公开定义的 但是在前面的代码中,按钮对象是在 Form1 类中私有定义的。 那么鼠标点击如何访问按钮的事件呢!

namespace PublisherAndSubscriber2ndNameSpace
{
class PublisherSubscriberPattern
{
    static void Main(string[] args)
    {
        Console.WriteLine("want to throw the ball");
        int decision = int.Parse(Console.ReadLine());

        PublisherBall puball = new PublisherBall();

        FielderSubscriber fielder = new FielderSubscriber(puball);

        // this is like the basic way to raise events, how i learnt it.
        // but i wanted to know how the mouse click raises button's event
        if (Convert.ToBoolean(decision))
        {
            puball.OnThrowEvent(new BallEventArgs() { Speed = 1001 });
        }


        Console.WriteLine("throw a ball");
        int selectBall;
        while (!Console.ReadKey().Equals(ConsoleKey.Escape))
        {
            Console.WriteLine("Enter a ball to throw 1 2 3 4");
            selectBall = int.Parse(Console.ReadLine());

            // trying to simulate a mouse click by using keyboard key value
            // Here I can only access PublishingBall objets because they are defined public in FielderSubscriber class
            switch (selectBall)
            {
                case 1: fielder.pace.OnThrowEvent(new BallEventArgs() { Speed = 162 });
                    break;
                case 2: fielder.spin.OnThrowEvent(new BallEventArgs() { Speed = 90 });
                    break;
                case 3: fielder.googly.OnThrowEvent(new BallEventArgs() { Speed = 50 });
                    break;
                case 4: fielder.bouncer.OnThrowEvent(new BallEventArgs() { Speed = 150 });
                    break;
                default: Console.WriteLine("enter between 1 to 4");
                    break;
            }
        }
    }
}

// Custom eventArgs defined for the PublisherBall 
class BallEventArgs : EventArgs
{
    public int Speed { get; set; }
}

// This class is analogous to a button class
class PublisherBall
{
    public event EventHandler<BallEventArgs> Throw = delegate { };

    public void OnThrowEvent(BallEventArgs e)
    {
        Throw(this, e);
    }
}

// This class is analogous to the Form1 class where i would Instantiate the button objects(private)
class FielderSubscriber
{
    public PublisherBall pace;
    public PublisherBall spin;
    public PublisherBall googly;
    public PublisherBall bouncer;

    // one way is to send the PublisherBall's object to the constructor
    public FielderSubscriber(PublisherBall ball)
    {
        ball.Throw += ball_Throw;
        InitializeComponent();
    }

    void InitializeComponent()
    {
        pace = new PublisherBall();
        pace.Throw += pace_Throw;

        spin = new PublisherBall();
        spin.Throw += spin_Throw;

        googly = new PublisherBall();
        googly.Throw += googly_Throw;

        bouncer = new PublisherBall();
        bouncer.Throw += bouncer_Throw;
    }

    void bouncer_Throw(object sender, BallEventArgs e)
    {
        Console.WriteLine("A bouncer @{0}kmph", e.Speed);
    }

    void googly_Throw(object sender, BallEventArgs e)
    {
        Console.WriteLine("A googly @{0}kmph", e.Speed);
    }

    void spin_Throw(object sender, BallEventArgs e)
    {
        Console.WriteLine("A spin @{0}kmph", e.Speed);
    }

    void pace_Throw(object sender, BallEventArgs e)
    {
        Console.WriteLine("A pace @{0}kmph", e.Speed);
    }

    // An Event Handler method
    void ball_Throw(object sender, BallEventArgs e)
    {
        if (e.Speed > 100)
            Console.WriteLine("wew tough catch {0}kmph", e.Speed);
        else
            Console.WriteLine("easy catch {0}kmph");
    }
}
}
//P.S I am a total noob , please be gentle

【问题讨论】:

  • 第一个例子是 Windows 窗体不是 WPF
  • 啊,我的错,你是对的
  • @Marcin Iwanowski 作为一个附带问题,这是创建和引发事件的正确方法还是有更好的方法来做到这一点,w.r.t 发布者和订阅者模式?
  • 我只注意到在您的 FielderSubscriber 类中,您永远不会脱离事件。在这个特定的程序中没有关系,但是如果你在另一个代码中使用它,那么在 PublisherBall 对象处于活动状态之前,GC 不会收集 fielder 对象。

标签: c# wpf events


【解决方案1】:

Button 在 Windows 窗体中的工作方式要复杂得多。如您所见,使用 Reflector 或类似工具,Button 类继承自 ButtonBase,并且存在接受消息的受保护 WndProc 方法。如果消息包含“单击”代码,则此方法引发 Click 事件。简而言之,添加到可视化树(显示)的每个控件都会从 Window 循环接收消息,无论该特定窗口上发生什么。如果控件认为该消息很重要,则它会引发适当的事件。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-21
    • 1970-01-01
    • 1970-01-01
    • 2018-03-15
    • 1970-01-01
    相关资源
    最近更新 更多