16.1. C# GUIs: A Primer

The fundamental approach to GUI programming with virtually any programming language, C# or otherwise, is to assemble graphical building blocks generically called components (and, in C#, often referred to specifically as controls). We assemble them in specific ways to provide the look, or presentation, that we desire for an application, and then program their behind-the-scenes logic to enable them to do useful things. Users interact with GUI components—buttons, text fields, lists, and so on—to provide information to the system and/or to obtain information from the system to achieve some worthwhile goal: in other words, to fulfill the use cases that we identified in Chapter 9.

One of the many advantages of C# is that GUI development is supported by the FCL. Every aspect of our C# application—the domain classes/objects, persistence of the state of these objects to a file, GUI manipulation of these objects, and so on—can be conveniently programmed using FCL types. Therefore, the components that will make up the GUI are objects and can interact with the domain model objects from the SRS. In the case of the SRS GUI, for example, we'll be doing the following:

  • Instantiating objects: For example, when a student user logs on to the system, we'll instantiate a Student object as an abstraction of that user.

  • Invoking their methods: As we do when we invoke the soon-to-be-written ValidatePassword method on a Student object to ensure that the password a user has typed is valid.

  • Changing their states: Modifying field values and/or creating new links between the objects; for example, when a student successfully enrolls in a course, we'll form a link between the appropriate Student and Section objects.

Because the GUI itself consists of objects, the GUI components

  • Are described by classes

  • Are instantiated via the new operator, using an appropriate constructor

  • Have fields (which are typically private) and properties/methods (which are typically public) that we access via dot notation

  • Communicate via method calls

  • Participate in inheritance hierarchies

  • Are referenced by reference variables, when we want to maintain named object references to them

  • Maintain references to other objects—GUI objects as well as non-GUI objects

  • Collaborate with other objects—GUI as well as non-GUI objects—to accomplish the mission of the overall system

Therefore, all the techniques that you've learned about creating and communicating with objects in general throughout this book will apply to GUI objects in particular. Through user interactions with the SRS GUI, the GUI's objects will be requested to perform functions, which in many cases lead them to collaborate behind the scenes with the domain objects—Students, Professors, Courses, Sections, and so on—to carry out a particular user-requested operation such as registering for a course.

16.1.1. Containers

Just as we often use collections to organize object references (e.g., a List to organize Student references), we assemble C# GUIs by organizing collections of components using a special type of GUI object known as a container. We may depict the relationship between containers, components, and objects via a UML diagram, as shown in Figure 16-1. A container is a component (by virtue of inheritance) just as all components and containers are objects because they derive from the Object class. However, every GUI component is not necessarily a container. Furthermore, because a container can contain components, and a container is a component, a container can contain other containers. In fact, this is the way that we build up complex GUIs—by embedding components in containers, a technique that we'll explore in depth in this chapter.

Figure 16.1. Relationship of containers to components

A container is like a directory on your computer system, and the objects placed in it are like items placed within that directory.

  • Just as any one file has only one home directory, any one object can be placed in only one container.

  • Conversely, a container can contain many objects—including other containers—just as a directory can contain many files and/or other directories.

Containers available in C# include the Form class of the System.Windows.Forms namespace, which we'll use as our top-level container when we construct our SRS GUI.

16.1.2. GUIs Are Event-Driven

The C# GUI model is an event-driven system, in which each visual object can generate a number of events based on a user's interaction with that object. For example, clicking a graphical button, pressing the Enter key on the keyboard after typing in a text field, or clicking an item within a list to select it all automatically generate events.

Events are the system's way of telling us that the user has interacted with the GUI in some fashion. Events are informational in nature; as application developers, we can choose to program a response to an event or to ignore it as we see fit. We'll discuss events and event handling in more detail later in this chapter.

16.1.3. System.Windows.Forms and System.Drawing Namespaces

The GUI classes and support classes that we'll discuss in this chapter can be found in the System.Windows.Forms and System.Drawing namespaces of the .NET FCL. These C# namespaces provide an extensive array of ready-made GUI classes:

  • The System.Windows.Forms namespace contains predefined GUI classes that represent buttons, labels, menus, windows, panels, and many other things besides. We can extend the existing GUI classes to create our own custom GUI classes.

  • The System.Windows.Forms namespace also contains a variety of delegate types. A delegate is a C# class that can be used to respond to events generated by a GUI object. We'll discuss delegates when we discuss C# event handling later in this chapter.

  • The System.Drawing namespace contains support classes that can be used for such operations as changing a font, adding color to a GUI object, or defining a geometrical construct such as a point or a rectangle.

Before we dive into the details of the classes defined by the GUI libraries of the .NET FCL, however, let's take a step back and talk about some fundamental concepts of proper GUI design.

16.1.4. Separating the Model from the View

A technique known as separating the model from the view is an important design approach when developing a graphically oriented application. This concept relates to the Model-View-Controller (MVC) paradigm, which was popularized as a formal concept with the Smalltalk language, but is equally applicable to all object-oriented (OO) languages, including C#.

MVC is a way of thinking of an application as being subdivided into three parts: the model, the view, and the controller:

  • The model embodies the abstract domain knowledge of the application; that is, the objects/classes that represent the real-world items/issues that the users of an application are familiar with, often referred to as the business logic or domain of the application. Up until this point in the book, we've been focusing almost exclusively on these so-called domain classes: Person, Student, Professor, Course, Section, and the like.

  • The view is the way in which we present this knowledge to the user—typically, although not exclusively, via a GUI. Note that there can be many different views of the same model, in either the same or different applications. For example, with respect to the SRS GUI, we could represent the Students enrolled in a particular Section as a list of their names and student ID numbers; or as photographs; or in diagram form, as shown in Figures 16-2 through 16-4.

    Figure 16.2. Using a list to display Student information

    Figure 16.3. Using photographs to display Student information

    Figure 16.4. Using a diagram to display Student information
  • The controller is the automatic mechanism by which the user interface is displayed, and by which events are communicated back and forth between the model and the view; changes to the model are reflected in the view, and user interactions with the view trigger changes to the model. In the case of C#, this is handled by the .NET runtime in conjunction with the underlying windowing mechanism of your particular computer system.

As OO developers, we must do the following

  • Design and program the model, as we did throughout Part Two of the book and in Chapter 14, respectively.

  • Design and program the view(s); in C#, this is accomplished through the use of the FCL GUI namespaces that provide the graphical user interface building blocks we'll focus our attention on for much of this chapter.

  • Understand how the controller works in order to take advantage of the mechanism for connecting the model and view together. This involves learning the C# approach to event handling, (discussed later in this chapter).

When designing and programming an application, if we take care to separate the model and view elements by placing the code for those elements in different classes, it becomes much easier to accomplish the following:

  • Add or change a view, if need be, without disturbing the underlying model: In essence, this is what we'll be doing when we add a GUI view to the SRS application later in this chapter. As you'll see, the domain classes that we've already programmed will remain virtually unchanged by our addition of a GUI; and, those changes that we do make to the domain classes will be to enhance their abstractions, not to introduce GUI features.

  • Provide multiple alternative views of the same underlying model: Sometimes we provide different views for different categories of user; for example, a professor using the SRS might see different windows and options than a student would see.

  • Give a single user the ability to switch among multiple views: A familiar example of this can be found within the Microsoft Windows operating system. With Windows, users can view the contents of a folder as icons, as a detailed list, as an HTML page, or even as a DOS directory listing, as shown in Figures 16-5 through 16-8.

Figure 16.5. Viewing folder contents as icons

Figure 16.6. Or viewing folder contents as a detailed list

Figure 16.7. Or viewing folder contents as an HTML page

Figure 16.8. Or viewing folder contents as a DOS directory listing

Regardless of the view chosen, however, the underlying model in our Windows example is the same: we have a directory titled Different Views on our file system, and it contains four files: two text documents, a GIF image, and a PowerPoint presentation, as reflected in the Unified Modeling Language (UML) diagram in Figure 16-9. The Windows File System Component in the figure would be implemented as an abstract class that represents either a File or a Folder, and would declare members common to both File and Folder objects (a name, a creation date, a read-only flag, and so on).

Figure 16.9. The UML model underlying all Windows views

Our model should, in essence, be unaffected by the current view; just as we can change the appearance of a sofa by adding a slipcover without changing its underlying structure or general functionality, so too should we be able to change the visual appearance of an application without changing its underlying structure.

One way to help ensure that the model and view are logically separated is to develop the model first, without regard for the view. In theory, if we do a proper job of developing the model, based on the analysis techniques of Part Two, virtually any view relevant to the original goals (use cases) set forth for the system should be attainable. We'll demonstrate this concept by retroactively adding a GUI to the model that we automated in Chapters 14 and 15.

16.1.5. Our Learning Roadmap

We'll learn about building C# GUIs in three stages:

  • First, you'll learn how to describe the desired look and behavior of our GUI by preparing a concept of operations document.

  • Second, you'll learn about the various classes and techniques used in producing the visual appearance of a GUI.

  • Finally, you'll learn how to provide behavior to the GUI through event handling.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset