This is your first visit inside The Matrix. Welcome!

The Matrix has you…

This place will take you into the mirage of learning C# programming language, without any previous coding experience being required

Follow the White Rabbit…█

Close
Friday, November 24, 2017 16:26

Control Events

In computer programming, event-driven programming is a programming paradigm in which the flow of the execution of a program is determined by events such as user actions (mouse clicks, key presses), sensor outputs, or messages from other programs/threads.

Because C# is also an event-driven programming language, today we will learn about events. Events are quite a complex concept which can confuse even advanced programmers, and they are actually comprised of events, events handlers and delegates, but for our beginner level, we will learn only the basics of events concept.

At the most basic concept, events are messages signaling that something has happened. For instance, when we click a button, some action is performed. In other words, the program received a click event, signaling to it that a mouse click has happened somewhere in our program, and that a certain action needs to be executed for that event. In short, events are messages to the computer that some action has occurred.

Event handlers, on the other side, are the pieces of code that should be executed when a certain event happens, and they look almost like normal methods, with just some unknown parameters type. Event handler methods have the same signatures as the events.

But, enough with talking. Let’s see how we are practically dealing with events and how can they be useful to us. I have said in a previous lesson that visual controls have properties, methods and events.  Control events help us interact with the visual controls of our interfaces.

Lets take the the same button example we used in our previous lesson. We had this XAML code:

<Window x:Class="HelloWorldWPF.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:HelloWorldWPF"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525" WindowStartupLocation="CenterScreen">
    <Grid x:Name="myContainer">
        <Button Content="Click!" Margin="189,195,253,104" Background="#FF530909" BorderBrush="#FFFF00B9" Foreground="White"/>

    </Grid>
</Window>

Now, when we select our button in the visual editor, we can now see a list of events available for the selected control, located also in the Properties panel of Visual Studio. However, we need to first click on the little thunderbolt icon:

events panel

As you can see, when we select a control, the Properties Panel will allow us to switch between the control properties and control events. You can also see a huge list of events that are available for our button control, the most important of it being, obviously, the Click event, which will be raised when we click our button. Because that’s what buttons are made for, to be clicked :)) .

So, we now know where the events of our buttons reside. But how do we specify a piece of code that should be executed when a certain event is triggered? I explained earlier that the thing that deals with this is called event handler, and I was also saying that event handlers look like normal methods, with the only difference that they have some weird looking parameters. So, how do we specify an event handler? Do we write the method ourselves? Fortunately, no. Visual Studio is complex enough to automate this for us. All we need to do is double click inside the text field of some event, and Visual Studio will create the event handler method automatically

automatic event handler

When we double clicked in the Click event text box from the list of events, Visual Studio automatically created an event handler method for us, called Button_Click. However, if we want to give a custom name to our event handler method, we can manually type its name:

manual event handler

If we will check our XAML codes now, we will notice that the button codes have been slightly modified:

<Window x:Class="HelloWorldWPF.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:HelloWorldWPF"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525" WindowStartupLocation="CenterScreen">
    <Grid x:Name="myContainer">
        <Button Content="Click!" Margin="189,195,253,104" Background="#FF530909" BorderBrush="#FFFF00B9" Foreground="White" Click="OnButtonClick"/>

    </Grid>
</Window>

This means that we can manually set events to our controls directly in our XAML codes, just like we can set their properties. However, we need to assign a method who’s signature is valid for the specified event signature. In other words, the parameters of the specified method needs to match the parameters of the event. We cannot specify any method as event handler. This because when a control triggers an event, it usually sends some additional information along with the event, such as who generated the event, and the properties of that event. Let’s take a look at our generated event handler for the Click event of our button:

using System.Windows;

namespace HelloWorldWPF
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void OnButtonClick(object sender, RoutedEventArgs e)
        {

        }
    }
}

We notice that the name of the function is the one we specified when we created the event, and we notice that it has two parameters: object sender and RoutedEventArgs e.

The first parameter is an object type, as I explained in some earlier lesson that object is the parent of all other types in .NET. It will always indicate the sender (hence its name) of the event, or the control that generated the event. Since our button has no name, how do we know who generated the click event? Maybe we want to change the text of a button when we click it, and we have more than one button. How do we tell the program which button was clicked and generated the Click event, so we can change its text?

Well, since the sender object will always be the object that generated the event, we can obviously use this sender parameter to tell who raised the event. However, it is not that simple. I already said that object is the parent type of all types in .NET. This means that an object CAN be a button, but it ALSO can be something else. This means that in order to avoid any confusions and errors, we need to cast the sender object back to the type that generated the event, in our case, cast it back to type Button:

using System.Windows;

namespace HelloWorldWPF
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void OnButtonClick(object sender, RoutedEventArgs e)
        {
             ((Button)sender).Content = "New Content";
        }
    }
}

First, we cast our sender object to type Button. That will offer us a Button object, to which we can access its control properties, like Content, Size, etc. However, this can cause exceptions that can crash our program, if we cast the sender object to an invalid type, such as float, for example. Since both Button and float derive from object type, the C# compiler allows us to cast our sender to float. However, since our sender is obviously not a float, this will generate an error. To avoid such dangers, we can use the as operator:

using System.Windows;

namespace HelloWorldWPF
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void OnButtonClick(object sender, RoutedEventArgs e)
        {
             (sender as Button).Content = "New Content";
        }
    }
}

Additionally, we can even specifically check if a sender object is of a certain type, using the is operator:

using System.Windows;

namespace HelloWorldWPF
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void OnButtonClick(object sender, RoutedEventArgs e)
        {
            if (sender is Button)
            {
                (sender as Button).Content = "New Content";
            }
        }
    }
}

When we click our button, the above code will check if the sender of the event is of type Button, and if yes, it will change its text.

We said that our second parameter, e, is actually the event itself, and we can access the additional parameters that it carries. To better illustrate this, lets add another control to our window. Drag and drop a TextBox from the Toolbox over your window, in Visual Designer, or create a TextBox in the XAML codes. After that, double click on the KeyUp event, in the Events panel, as I already showed. The XAML should look approximately like this:

<Window x:Class="HelloWorldWPF.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:HelloWorldWPF"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525" WindowStartupLocation="CenterScreen">
    <Grid x:Name="myContainer">
        <Button Content="Click!" Margin="189,195,253,104" Background="#FF530909" BorderBrush="#FFFF00B9" Foreground="White" Click="OnButtonClick"/>
        <TextBox HorizontalAlignment="Left" Height="23" Margin="145,120,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="120" KeyUp="TextBox_KeyUp"/>

    </Grid>
</Window>

The KeyUp event is the event that is triggered when we press and release a key, while the control is focused. Lets say that we want to know when the user presses the Enter key in our TextBox. Since we just found out that we can use the KeyUp event to know when the user types in our TextBox, all that remains to be done is to add a piece of code inside the KeyUp event handler of our TextBox, that will tell us when the Enter key was pressed. The only difficult thing is… we don’t know WHICH keys are the users pressing. How do we know if they press Space, Backspace or Enter? Fortunately for us, we do know. I said that the e parameter is the event itself, along with all its parameters. In the case of a TextBox, one of the parameters of the KeyUp event is… well, the key that generated the KeyUp event. You may ask yourself: “But, wait, isn’t that the sender? Shouldn’t the sender indicate the key that was pressed? Isn’t the key the one that generated the event?” Well, no! The TextBox is the sender, the pressed key is just a parameter of the event.

Let’s access the property that will give us the pressed key:

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

namespace HelloWorldWPF
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void TextBox_KeyUp(object sender, KeyEventArgs e)
        {
            MessageBox.Show(e.Key.ToString());
        }
    }
}

So, we can use the property Key of the parameter e to find out which key was pressed. We can even use this inside an if check:

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

namespace HelloWorldWPF
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void TextBox_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter)
            {
                MessageBox.Show("Enter was pressed!");
            }
        }
    }
}

When you will press the Enter key while the TextBox is focused, a message dialog box will appear, displaying a text.

You will rarely use the sender and e parameters of events, however, you should be aware of their existence. In any case, you will be using control events A LOT. In the future lessons, I will also list the most commonly used events of each control.

Comments

comments

Tags: , , , ,

Leave a Reply