Gigi Labs

Please follow Gigi Labs for the latest articles. Programmer's Ranch no longer has its domain, so please update your bookmarks and links to programmersranch.blogspot.com.

Saturday, July 5, 2014

C# WPF: Basic Login Form using a Grid

Hello everyone! :)

The articles I've written about WPF so far have dealt with how to do specific, sometimes advanced stuff.

In this article, I'd like to start covering some of the basics of WPF that a new WPF developer will need to know. WPF (Windows Presentation Foundation) is Microsoft's latest technology for developing desktop applications - the successor of the earlier but still strong Windows Forms technology. You can do WPF using Visual Studio or SharpDevelop, but unfortunately, it is not supported in the Mono environment and so you can't use it on non-Windows operating systems.

In today's article we'll learn how to use some basic controls and lay them out in a grid to create a login form. When I say "controls", it means any visual element - buttons, text fields, checkboxes, etc. Let's discover WPF by diving right into it! :)

In Visual Studio, go File -> New -> Project... and among the categories on the left, make sure "Windows" (under "Visual C#", not "Visual Basic") is selected. Then, in the middle part, select "WPF Application". Give it a name, select a location, and you're good to go.


When the project loads up, you'll see the screen divided into a few parts. On the right, there's the Solution Explorer where you can see your source files as usual. The main portion of the screen contains a preview of what your window currently looks like, and below it is an editor where you can write XAML to build the contents of your window.


In WPF, the visual stuff like buttons, text fields and the like are defined using XAML. If you look at the default XAML, there's just a <Window> element that contains an empty <Grid> element. You can build up just about any user interface using just <Grid> and a few other layout elements. Let's take a look at what the <Grid> can do for us.

If you open up the Toolbox panel on the left, you'll find that there are many different items you can just drag onto the empty window. Drag a button onto it.


The button is added to your window thanks to this XAML that has been added inside your <Grid>:

    <Button Content="Button"
        HorizontalAlignment="Left"
        Margin="159,113,0,0"
        VerticalAlignment="Top"
        Width="75" />

Among the attributes, you'll notice there is a Margin. In this case, this is being used to position the button relative to the grid. The values are relative to the left and top of the window. Try changing them and see how the button moves. This usage of the <Grid> makes it pretty much like a canvas, where you can put controls wherever you like, even on top of each other.

A more common way to use a <Grid> is to lay out controls in a tabular format, with rows and columns. To do this, you'll first need to define a number of rows and columns inside the grid. Remove the button and set up the grid like this instead:

    <Grid>

        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>

        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>

        <!-- Controls go here -->

    </Grid>


What we're doing here is setting up the <Grid> to have two rows and two columns. In fact, you should now be able to see the window divided into four cells in the preview:


We can now start adding controls in the part where I put a placeholder comment. Let's replace the comment with this <TextBlock>:

        <TextBlock Grid.Row="0"
                   Grid.Column="0"
                   Text="Username:" />

If you've ever used HTML, you're probably huffing and puffing at this stage. In WPF, you need to define a row and column structure beforehand, and you need to tell the controls into which row and column they belong. We do this by using the Grid.Row and Grid.Column properties. Setting both to zero puts the control into the top-left cell.

<TextBlock> is a simple control that displays text (similar to a label); the user cannot interact with it. Its text can be set using the Text property as above.

Let us now add a text field where the user can enter his username:

        <TextBox Grid.Row="0"
                 Grid.Column="1"
                 Name="UsernameField" />

We use the <TextBox> element to define a text field. Apart from positioning it in the top-right cell, we're also giving it a Name - we'll use this later to retrieve the contents of the text field from code.

Now, let's add another <TextBlock> and text field for the password. However, for passwords we should use the <PasswordBox>, which provides security benefits including masking the input text. Add the following elements for the password:


        <TextBlock Grid.Row="1"
                   Grid.Column="0"
                   Text="Password:" />

        <PasswordBox Grid.Row="1"
                     Grid.Column="1"
                     Name="PasswordField" />

The text fields can be a bit difficult to see in the preview. Press F5 to run the application and see the actual window:



OK, it looks something like a login form. But can we make it look better? One thing we can do is limit the height of each row, so that the fields don't look so massive. And while we're at it, let's add a third row in which we will later add a button to actually perform the login operation:


        <Grid.RowDefinitions>
            <RowDefinition Height="30" />
            <RowDefinition Height="30" />
            <RowDefinition Height="30" />
        </Grid.RowDefinitions>

This has the following effect on the form (note how third row is nowhere to be seen since it doesn't have any controls just yet):


We can then center the <TextBlock>s vertically to align them better with the text fields. We do this by setting VerticalAlignment="Center" on each of them. Another improvement we can make is to set a small margin on all the controls (Margin="2"), to space them out a little:


There's still some room for improvement, but let's now turn our attention to getting the login form working. First, we need a button. Add the following:

        <Button Grid.Row="2"
                Grid.Column="0"
                Grid.ColumnSpan="2"
                Name="LoginButton"
                Margin="2">Login</Button>

You'll notice a new property in there: Grid.ColumnSpan. This allows the button to take up more than one cell - in fact we're make it span across two columns.

Add a Click property. As you're about to set its value, Intellisense prompts you to create a new event handler:


If you press TAB, the value is filled out for you: Click="LoginButton_Click". But what is this LoginButton_Click? You see, the file you've been working on so far is MainWindow.xaml, but as you can see in Solution Explorer, there's a file called MainWindow.xaml.cs that is associated with it. This is called the codebehind, and your logic code can go here. In it, you'll find some code:

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

        private void LoginButton_Click(object sender, RoutedEventArgs e)
        {

        }
    }

Aside from the constructor, you'll notice there is the event handler for the login button that we generated a moment ago. In here, you can work with the fields using the name we gave them in the XAML...

            string username = this.UsernameField.Text;
            string password = this.PasswordField.Password;

...and also perform any logic you need, in this case the actual login. Let's get this working by adding the following code:

            if (username == "flynn" && password == "carsen")
                MessageBox.Show("Logged in!", "Success");
            else
                MessageBox.Show("Invalid username or password.", "Login failed");

You can now run the application and try it out:


You'll notice that you can't press ENTER to login; you have to click on the button. You can resolve this by adding IsDefault="True" to the button in the XAML. This will make it the default button for the window, and pressing ENTER will cause its Click event to fire.

Very good! We have made a working login form in WPF.

In this article, we learned about some of the basic WPF controls, and also two different ways to use a <Grid> to lay out other controls. We created a login form to explore basic usage of all these controls. We also attached an event handler to our button control, and added logic in the codebehind to perform the login.

Thanks for reading, and stay tuned for more! :)

No comments:

Post a Comment