Appendix A: Answers To The Test Your Knowledge Questions
Appendix A: Answers To The Test Your Knowledge Questions
Appendix A: Answers To The Test Your Knowledge Questions
Appendix A
Answers to the Test Your
Knowledge Questions
This appendix has the answers to the questions in the Test Your Knowledge section at the end of
each chapter.
Answer: https://stackoverflow.com/.
Appendix A
Chapter 2 – Speaking C#
Exercise 2.1 – Test your knowledge
What type would you choose for the following "numbers?"
Answer:
The code will loop forever because the value of i can only be between 0 and 255. Once
i gets incremented beyond 255, it loops back to 0 and therefore will always be less than
the max (500).
To prevent the infinite loop, you can add a checked statement around the code. This
would cause an exception to be thrown after 255 due to the overflow, as shown in the
following output:
254
255
System.OverflowException says Arithmetic operation resulted in an
overflow.
Answer: x is 4 and y is 6
2. What are the values of x and y after the following statements execute?
x = 3 << 2;
y = 10 >> 1;
Answer: x is 12 and y is 5
Answers to the Test Your Knowledge Questions
3. What are the values of x and y after the following statements execute?
x = 10 & 8;
y = 10 | 7;
Answer: x is 8 and y is 15
8. When writing a unit test using xUnit, what attribute must you decorate the test
methods with?
Answer: [Fact].
9. What dotnet command executes xUnit tests?
Answer: dotnet test.
10. What is TDD?
Answer: Test-Driven Development.
More Information: You can read about TDD in an article about unit testing
at the following link: https://docs.microsoft.com/en-us/dotnet/core/
testing/
2. What is the difference between the static, const, and readonly keywords when
applied to a type member?
Answer: The difference between the static, const, and readonly keywords when
applied to a type member are described in the following list:
• static: This keyword makes the member shared by all instances and it must be
accessed through the type, not an instance of the type.
• const: This keyword makes the field a fixed literal value that must never change
because during the compilation, assemblies that use the field copy the literal
value at the time of compilation.
Answers to the Test Your Knowledge Questions
• readonly: This keyword restricts the field so that it can only be assigned to
using a constructor or field initializer at runtime.
2. What is an event?
Answer: An event is a field that is a delegate having the event keyword applied. The
keyword ensures that only += and -= are used; this safely combines multiple delegates
without replacing any existing event handlers.
3. How are a base class and a derived class related and how can the derived class access
the base class?
Answer: A derived class (or subclass) is a class that inherits from a base class (or
superclass). Inside a derived class you use the base keyword to access the class that
the subclass inherits from.
4. What is the difference between the is and as operators?
Answer: The is operator returns true if an object can be cast to the type; otherwise it
returns false. The as operator returns a reference to the object if an object can be cast to
the type; otherwise, it returns null.
5. Which keyword is used to prevent a class from being derived from, or a method from
being overridden?
Answer: sealed.
More Information: You can read about the sealed keyword at the
following link: https://docs.microsoft.com/en-us/dotnet/
csharp/language-reference/keywords/sealed
6. Which keyword is used to prevent a class from being instantiated with the new keyword?
Answer: abstract.
More Information: You can read about the virtual keyword at the
following link: https://docs.microsoft.com/en-us/dotnet/
csharp/language-reference/keywords/virtual
9. What are the signatures of the constructors that all exceptions should have?
Answer: The signatures of the three constructors that all exceptions should have are
shown in the following list:
• A constructor with no parameters.
• A constructor with a string parameter, usually named message.
• A constructor with a string parameter, usually named message, and an
Exception parameter, usually named innerException.
Decompiling can also be useful when calling a third-party library that you need to
better understand how it works to call it appropriately.
4. Which .NET type does the C# float alias represent?
Answer: System.Single.
5. What tool should you use before porting an application from .NET Framework to .NET
5?
Answer: You should use the .NET Portability Analyzer before porting an application
from .NET Framework to .NET 5.
6. What is the difference between framework-dependent and self-contained deployments
of .NET Core applications?
Answer: Framework-dependent .NET Core applications require .NET Core to exist
for an operating system to execute. Self-contained .NET Core applications include
everything necessary to execute on their own.
7. What is a RID?
Answer: RID is the acronym for Runtime Identifier. RID values are used to identify
target platforms where a .NET Core application runs.
8. What is the difference between the dotnet pack and dotnet publish commands?
Answer: The dotnet pack command creates a NuGet package. The dotnet publish
command puts the application and its dependencies into a folder for deployment to a
hosting system.
9. What types of applications written for .NET Framework can be ported to .NET Core 3.0
or later?
Answer: Console, ASP.NET MVC, ASP.NET Web API, Windows Forms, and Windows
Presentation Foundation (WPF).
10. Can you use packages written for .NET Framework with .NET 5?
Answer: Yes, as long as they only call APIs in .NET Standard 2.0.
More Information: You can read about why you should simplify the way
you validate email addresses at the following links: https://davidcel.is/
posts/stop-validating-email-addresses-with-regex/ and https://
stackoverflow.com/questions/201323/how-to-validate-an-email-
address-using-a-regular-expression
• StreamReader is used for reading strings from a stream that can be any type of
text file, including XML and JSON.
More Information: You can read about when to use JSON versus
protocol buffers at the following link: https://stackoverflow.
com/questions/52409579/protocol-buffer-vs-json-when-to-
choose-one-over-another
10. Where can you find information about NuGet packages and their dependencies?
Answer: You can find information about NuGet packages and their dependencies at the
following link: https://www.nuget.org/.
Appendix A
10. SHA-1 is a hashing algorithm designed by the United States National Security Agency.
Why should you never use it?
Answer: SHA-1 is no longer secure. All modern browsers have stopped accepting
SHA-1 SSL certificates.
10. What benefit do you get from declaring entity navigation properties as virtual?
Answer: You can enable lazy loading if you declare entity navigation properties as
virtual.
More Information: You can read about the let keyword at the
following link: https://docs.microsoft.com/en-us/dotnet/
csharp/language-reference/keywords/let-clause
10. How can you create your own LINQ extension methods?
Answer: Create a static class with a static method with an IEnumerable<T> parameter
prefixed with this, as shown in the following code:
Appendix A
namespace System.LINQ
{
public static class MyLINQExtensionMethods
{
public static IEnumerable<T> MyChainableExtensionMethod<T>(
this IEnumerable<T> sequence)
{
// return something IEnumerable<T>
}
public static int? MyAggregateExtensionMethod<T>(
this IEnumerable<T> sequence)
{
// return some int value
}
}
}
3. By convention, what suffix should be applied to a method that returns Task or Task<T>?
Answer: Add the suffix Async to the method name, for example, for a synchronous
method named Open, use OpenAsync for the equivalent that returns a Task.
Answers to the Test Your Knowledge Questions
4. To use the await keyword inside a method, which keyword must be applied to the
method declaration?
Answer: The async keyword must be applied to the method declaration.
5. How do you create a child task?
Answer: Call the Task.Factory.StartNew method with the TaskCreationOptions.
AttachToParent option to create a child task.
6. Why should you avoid the lock keyword?
Answer: The lock keyword does not allow you to specify a timeout; this can cause
deadlocks. Use the Monitor.Enter method and pass a TimeSpan argument as a timeout
and then call the Monitor.Exit method explicitly to release the lock at the end of your
work instead.
7. When should you use the Interlocked class?
Answer: You should use the Interlocked class to modify integers and floating-point
numbers that are shared between multiple threads.
8. When should you use the Mutex class instead of the Monitor class?
Answer: Use Mutex when you need to share a resource across process boundaries.
Monitor only works on resources inside the current process.
9. What is the benefit of using async and await in a website or web service?
Answer: In a website or web service, using async and await improves scalability, but
not the performance of a specific request because extra work of handling over work
between threads is required.
10. Can you cancel a task? How?
Answer: Yes, you can cancel a task, as described at the following link: https://docs.
microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/cancel-an-
async-task-or-a-list-of-tasks.
2. List six status codes and their descriptions that can be returned in an HTTP response.
Answer: 200 OK, 201 Created, 301 Moved Permanently, 400 Bad Request, 404 Not
Found (missing resource), 500 Internal Server Error. Others include 101 Switching
Protocols (e.g. from HTTP to WebSocket), 202 Accepted, 204 No Content, 304 Not
Modified, 401 Unauthorized, 403 Forbidden, 406 Not Acceptable (for example,
requesting a response format that is not supported by a website), and 503 Service
Unavailable.
6. How do you mix C# code into the middle of HTML to create a dynamic page?
Answer: To mix C# code into the middle of HTML to create a dynamic page, you can
create a Razor file with the .cshtml file extension, and then prefix any C# expressions
with the @ symbol, and for C# statements wrap them in braces or create a @functions
section, as shown in the following markup:
@page
@functions
{
public string[] DaysOfTheWeek
{
get => System.Threading.Thread.CurrentThread
.CurrentCulture.DateTimeFormat.DayNames;
}
{
get => System.DateTime.Now.ToString("dddd");
}
}
<html>
<head>
<title>Today is @WhatDayIsIt</title>
</head>
<body>
<h1>Days of the week in your culture</h1>
<ul>
@{
// to add a block of statements: use braces
foreach (string dayName in DaysOfTheWeek)
{
<li>@dayName</li>
}
}
</ul>
</body>
</html>
• In the Razor Page model class or @functions section, declare a private field
to store the data context and then set it in the constructor, as shown in the
following code:
private MyDataContext db;
10. How can you reuse Razor Pages with ASP.NET 2.2 or later?
Answer: To reuse Razor Pages with ASP.NET 2.2 or later, everything related to a Razor
page can be compiled into a class library. To create one, enter the following command:
dotnet new razorclasslib -s.
2. What are the names of the three segments defined in the default ASP.NET Core
MVC route, what do they represent, and which are optional?
Answer:
• {controller}: For example, /home represents a controller class to instantiate,
for example, HomeController. It is optional because it can use the default value:
Home.
• {action}: For example, /index represents an action method to execute, for
example, Index. It is optional because it can use the default value: Index.
Answers to the Test Your Knowledge Questions
• {id}: For example, /5 represents a parameter in the action method, for example,
int id. It is optional because it is suffixed with ?.
3. What does the default model binder do and what data types can it handle?
Answer: The default model binder sets parameters in the action method. It can handle
the following data types:
• Simple types like int, string, and DateTime, including nullable types.
• Complex types like Person and Product.
• Collections types like IEnumerable<T>.
4. In a shared layout file like _Layout.cshtml, how do you output the content of
the current view?
Answer: To output the content of the current view in a shared layout, call the
RenderBody method, as shown in the following markup:
@RenderBody()
5. In a shared layout file like _Layout.cshtml, how do you output a section that
the current view can supply content for, and how does the view supply the contents for
that section?
Answer: To output the content of a section in a shared layout, call the RenderSection
method specifying a name for the section and if it is required, as shown in the following
markup:
@RenderSection("Scripts", required: false)
To define the contents of the section in the view, create a named section, as shown in
the following markup:
@section Scripts
{
<script> alert('hello');
</script>
}
6. When calling the View method inside a controller's action method, what paths
are searched for the view by convention?
Answer: When calling the View method inside a controller's action method, three
paths are searched for the view by default, based on combinations of the names of the
controller and action method and a special Shared folder, as shown in the following
example output:
InvalidOperationException: The view 'Index' was not found. The following
locations were searched:
/Views/Home/Index.cshtml
/Views/Shared/Index.cshtml
/Pages/Shared/Index.cshtml
Appendix A
7. How can you instruct the visitor's browser to cache the response for 24 hours?
Answer: To instruct the visitor's browser to cache the response for 24 hours,
decorate the controller class or action method with the [ResponseCache] attribute,
and set the Duration parameter to 86400 seconds and the Location parameter to
ResponseCacheLocation.Client.
8. Why might you enable Razor Pages even if you are not creating any yourself?
Answer: If you have used features like ASP.NET Core Identity UI, then it requires
Razor Pages.
9. How does ASP.NET Core MVC identify classes that can act as controllers?
Answer: ASP.NET Core MVC identifies classes that can act as controllers by looking
to see if the class (or a class that it derives from) is decorated with the [Controller]
attribute.
10. In what ways does ASP.NET Core MVC make it easier to test a website?
2. What is the special relative URL path to access the Piranha CMS management user
interface and what is the username and password configured by default?
Answer: The special relative URL path to access the Piranha CMS management user
interface is /manager and the username and password configured by default is admin
and password.
3. What is a slug?
Answer: A slug is the relative URL path for a content item like a page or post.
4. What is the difference between saving content and publishing content?
Answer: The difference between saving content and publishing content is that saving
just saves the changes to the CMS database but publishing also makes those changes
visible to visitors.
5. What are the three Piranha CMS content types and what are they used for?
Answer: The three Piranha CMS content types are Sites, Pages, and Posts. Sites are
for property values that need to be shared across all pages. Pages are for normal web
pages. Posts are for special pages that can only be shown in an archive page with
sorting and filtering capabilities.
6. What are the three Piranha CMS component types and what are they used for?
Answer: The three Piranha CMS component types are Fields, Regions, and Blocks.
Fields are for simple data values like strings and numbers. Regions are for complex
data values that appear at a fixed location with a content type like a page. Blocks are for
complex data values that appear in any order and combination defined by the content
owner.
7. List three properties that a Page type inherits from its base classes and explain
what they are used for.
Answer: Three properties that a Page type inherits from its base classes include:
• ParentId: A Guid value that references its parent with the content tree.
• Blocks: An ordered collection of references to block instances.
• Published: A DateTime value that shows when the page was published for
visitors to view.
namespace NorthwindCms.Models
{
[PageType(Title = "Category Page", UseBlocks = false)]
[PageTypeRoute(Title = "Default", Route = "/category")]
public class CategoryPage : Page<CategoryPage>
{
[Region(Title = "Category detail")]
[RegionDescription("The details for this category.")]
public CategoryRegion CategoryDetail { get; set; }
10. How do you retrieve a page from the Piranha CMS database?
Answer: You retrieve a page from the Piranha CMS database by using the IApi
dependency service, as shown in the following code:
var model = await _api.Pages.GetByIdAsync<Models.CategoryPage>(id);
4. What must you do to specify what responses should be expected when calling an action
method?
Answer: To specify what responses should be expected when calling an action method,
decorate the action method with the [ProducesResponseType] attribute, as shown in the
following code:
// GET: api/customers/[id]
[HttpGet("{id}", Name = nameof(Get))] // named route
[ProducesResponseType(200, Type = typeof(Customer))]
[ProducesResponseType(404)]
public IActionResult Get(string id)
{
5. List three methods that can be called to return responses with different status
codes.
Answer: Three methods that can be called to return responses with different status
codes include:
• Ok: This returns the 200 status code and the object passed to Ok in the body.
• CreatedAtRoute: This returns the 201 status code and the object passed to this
method in the body.
• NoContentResult: This returns the 204 status code and an empty body.
• BadRequest: This returns the 400 status code and an optional error message.
• NotFound: This returns the 404 status code and an optional error message.
7. Why should you not wrap your use of HttpClient in a using statement to dispose of it
when you are finished even though it implements the IDisposable interface, and what
should you use instead?
Answer: HttpClient is shared, reentrant, and partially thread-safe so it is tricky to use
correctly in many scenarios. You should use HttpClientFactory, which was introduced
in .NET Core 2.1.
Appendix A
8. What does the acronym CORS stand for and why is it important to enable it in a web
service?
Answer: The acronym CORS stands for Cross-Origin Resource Sharing. It is important
to enable it for a web service because default browser same-origin policy prevents code
downloaded from one origin from accessing resources downloaded from a different
origin to improve security.
9. How can you enable clients to detect if your web service is healthy with ASP.NET Core
2.2 and later?
Answer: To enable clients to detect if your web service is healthy, you can install health
check APIs including database health checks for Entity Framework Core data contexts.
Health checks can be extended to report detailed information back to the client.
10. What benefits does endpoint routing provide?
6. What class must you instantiate to perform any machine learning task?
Answer: You must instantiate an MLContext to perform any machine learning task.
7. What is the difference between a label and a feature?
Answer: A feature is an input, for example, the tokenized text of an Amazon review. A
label is a value used to train the model and can be an output, for example, positive or
negative.
8. What does IDataView represent?
Answer: IDataView represents the input data for a machine learning task. It is
immutable, cursorable, lazily evaluated, heterogenous, and schematized.
9. What does the count parameter in the [KeyType(count: 10)] attribute represent?
Answer: The count parameter represents the maximum possible value that can be
stored in that column.
10. What does the score represent with matrix factorization?
Answer: The score with matrix factorization represents the likelihood of being a
positive case but it is not a probability in the traditional sense. The larger the score
value, the higher the likelihood.
2. In a Blazor Server website project, compared to an ASP.NET Core MVC website project,
what extra configuration is required in the Startup class?
Answer: In the Startup class, in the ConfigureServices method you must call
AddServerSideBlazor, and in the Configure method you must call MapBlazorHub and
MapFallbackToPage when setting up endpoints.
3. One of the benefits of Blazor is being able to implement client-side components using
C# and .NET instead of JavaScript. Does a Blazor component need any JavaScript?
Answer: Yes, Blazor components need some minimal JavaScript. For Blazor Server this
is provided by the file _framework/blazor.server.js. For Blazor WebAssembly this is
provided by the file _framework/blazor.webassembly.js. Blazor WebAssembly with
PWA also uses a JavaScript service worker file service-worker.js.
4. In a Blazor Server website project, what does the App.razor file do?
Answer: The App.razor file configures a Router used by all Blazor components in the
current assembly. For example, it sets a default shared layout for components that
match a route and a view to use when no match is found.
5. What is a benefit of using the <NavLink> component?
Answer: A benefit of using the <NavLink> component is that it integrates with the Blazor
routing system so that the NavigationManager can then be used to programmatically
navigate between components.
6. How can you pass a value into a component?
Answer: You can pass a value into a component by decorating a public property in
the component with the [Parameter] attribute and then setting the attribute in the
component when using it, as shown in the following code:
// defining the component
@code {
[Parameter]
public string ButtonText { get; set; };
Answer: Two key differences in the Program class between a Blazor Server and Blazor
WebAssembly project are: (1) the use of WebAssemblyHostBuilder instead of Host.
CreateDefaultBuilder, and (2) the registering of an HttpClient with a base address of
the host environment.
To go to the next screen, push the next page onto the Navigation object, as shown in the
following code:
await Navigation.PushAsync(new CustomerDetails(c));
To return to the previous screen, pop the page from the Navigation object, as shown in
the following code:
await Navigation.PopAsync();
9. How do you show a pop-up modal message with simple button choices like Yes or No?
Answer: To show a pop-up modal message with simple button choices like Yes or No,
you can call the DisplayAlert method, as shown in the following code:
bool response = await DisplayAlert("Apple Survey",
"Do you like your iPhone 11 Pro?", "Yes", "No");
Answers to the Test Your Knowledge Questions
5. What is the difference between Margin and Padding for an element like a Button?
Answer: The difference between Margin and Padding for an element like a Button is that
Margin is outside the Border and Padding is inside the Border.
Appendix A
Answer: You might implement the IValueConverter interface when you want to
perform data binding between two incompatible types, for example, to convert an int
value into a string value that defines a path to an image, or between a floating-point
value representing a body-mass index (BMI) and a color that indicates good or bad
health.
Appendix B
Building Windows Desktop Apps
This appendix is about building applications for Windows desktop using three technologies:
Windows Forms, Windows Presentation Foundation (WPF), and Universal Windows
Platform (UWP).
Windows Forms and WPF support using .NET Core 3.0 or later as their runtime, but current
design-time support is limited so I only recommend this if you have existing Windows Forms
or WPF apps that must be migrated to modern .NET.
Most of this appendix will cover UWP apps that use the modern Windows Runtime and can
execute apps built using a custom version of .NET that compiles to native CPU instructions.
Although most of this appendix does not use .NET 5, in November 2021 Microsoft will release
.NET 6, which will be the single unified platform for .NET used by all app models, including
ASP.NET Core for web development, Windows Forms, WPF, and also cross-platform desktop
and mobile apps using .NET Multi-platform App User Interface (MAUI).
More Information: You can read more about your choices of platform for
building Windows desktop apps at the following link: https://docs.
microsoft.com/en-us/windows/apps/desktop/choose-your-platform.
You will explore some of the new user interface features of Fluent Design, introduced in the
Windows 10 Fall Creators Update in October 2017.
In a single appendix, we will only be able to scratch the surface of what can be achieved using
.NET for the Windows desktop. However, I hope to excite you into wanting to learn more
about the new ability to migrate legacy Windows applications to the modern .NET platform,
and the cool new UWP technology with Fluent Design, including template-able controls, data
binding, and animation!
UWP apps are not cross-platform, but they are cross-device, meaning they can run on desktop,
laptop, tablet, and mixed reality devices like the HP Windows Mixed Reality Headset. Those
devices must run a modern flavor of Windows. You will need Windows 10 May 2019 Update
and Visual Studio 2019 version 16.3 or later to use the latest features, like XAML Islands,
although older versions of Windows 10, like the April 2018 Update, should work for creating
the example app in this appendix.
In 1991, Microsoft introduced Visual Basic, which provided developers with a visual, drag-and-
drop-from-a-toolbox-of-controls way to build the user interface for Windows applications. It
was immensely popular, and the Visual Basic runtime is still part of Windows 10 today.
In 2002, Microsoft introduced .NET Framework, which included Windows Forms for building
Windows applications. The code could be written in either Visual Basic or C# languages.
Windows Forms had a similar drag and drop visual designer, although it generated C# or
Visual Basic code to define the user interface, which can be difficult for humans to understand
and edit directly.
In 2006, Microsoft introduced .NET Framework 3.0, which included WPF for building user
interfaces using XAML, which is easy for developers to understand and edit directly.
1. Download Microsoft Visual Studio 2019 version 16.8 or later for Windows from the
following link: https://visualstudio.microsoft.com/downloads/
2. Start the installer.
3. On the Workloads tab, select the following:
• .NET desktop development
• Universal Windows Platform development
• .NET Core cross-platform development
4. Click Install and wait for the installer to acquire the selected software and install it.
5. When the installation is complete, click Launch.
6. The first time that you run Visual Studio, you will be prompted to sign in. If you have a
Microsoft account, you can use that account. If you don't, then register for a new one at
the following link: https://signup.live.com/
7. The first time that you run Visual Studio, you will be prompted to configure your
environment. For Development Settings, choose Visual C#. For the color theme, I
chose Blue, but you can choose whatever tickles your fancy.
The following instructions start with creating some new folders to store a solution file and
a project. You can choose to use another tool to do this instead of Command Prompt, but
you should at least create the new solution and Windows Forms project by using the dotnet
command-line tool in the correct folder:
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net5.0-windows</TargetFramework>
<UseWindowsForms>true</UseWindowsForms>
</PropertyGroup>
</Project>
More Information: You can track the progress of the Windows Forms designer
at the following link: https://github.com/dotnet/winforms/tree/
master/docs/designer-releases
9. Navigate to Debug | Start Without Debugging or press Ctrl + F5, note the resizable
window with the title Form1, and then click the Close button in its top-right corner to
exit the application.
1. In Solution Explorer, open Program.cs and note that it is similar to a console app with
a Main entry point method, and that it instantiates a Form1 class and runs it, as shown in
the following code with comments removed to save space:
static class Program
{
[STAThread]
static void Main()
{
Application.SetHighDpiMode(HighDpiMode.SystemAware);
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
Building Windows Desktop Apps
2. In Solution Explorer, expand Form1.cs, open the Form1 class, and note it is a partial
class and the call to InitializeComponent in its constructor, as shown in the following
code:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
}
6. Drag and drop some controls, like Button, MonthCalendar, Label, and TextBox, onto
Form1, as shown in the following screenshot:
10. In Solution Explorer, right-click the solution and select Set StartUp Projects….
11. In the Solution 'WindowsDesktopApps' Properties Pages dialog box, for Startup
Project, select Current selection, and then click OK.
12. In Solution Explorer, select the LegacyWinForms project and note its name becomes
bold to indicate that it is the current selection.
13. Navigate to Debug | Start Without Debugging or press Ctrl + F5, click the button, and
note the month calendar animates to select Christmas Day, and then click the close
button in the top-right corner to exit the app.
Building Windows Desktop Apps
1. Drag and drop Form1 from the LegacyWinForms folder into the BasicWinForms folder,
which will prompt you to overwrite the following files:
• Form1.cs
• Form1.Designer.cs
• Form1.resx
2. In the BasicWinForms project, modify Program.cs to specify the legacy namespace when
instantiating and running Form1, as shown in the following code:
Application.Run(new LegacyWinForms.Form1());
More Information: You can read more about migrating WPF apps at the
following link: https://devblogs.microsoft.com/dotnet/migrating-a-
sample-wpf-app-to-net-core-3-part-1/
More Information: You can read more about the Windows Compatibility
Pack at the following link: https://devblogs.microsoft.com/dotnet/
announcing-the-windows-compatibility-pack-for-net-core/
Appendix B
UWP provides standard mechanisms to detect the capabilities of the current device and then
activate additional features of your app to fully take advantage of them.
UWP with XAML provides layout panels that adapt how they display their child controls to
make the most of the device they are currently running on. It is the Windows app equivalent of
web page responsive design. They also provide visual state triggers to alter the layout based on
dynamic changes, such as the horizontal or vertical orientation of a tablet.
Wave 1, available in Windows 10 Fall Creators Update, released in October 2017 and refined
in the subsequent waves as part of biannual Windows 10 updates, included the following
features:
• Acrylic material
• Connected animations
• Parallax views
• Reveal lighting
More Information: You can read more about how and when to use Acrylic
material at the following link: https://docs.microsoft.com/en-us/
windows/uwp/design/style/acrylic
More Information: You can read more about how and when to use connected
animations at the following link: https://docs.microsoft.com/en-us/
windows/uwp/design/motion/connected-animation
More Information: You can read more about Parallax at the following link:
https://docs.microsoft.com/en-us/windows/uwp/design/motion/
parallax
Reveal lighting helps the user understand which of the visual elements in the user interface is
an interactive element by lighting up as the user moves their mouse cursor over that element to
draw their focus.
More Information: You can read more about how and when to use Reveal to
bring focus to user interface elements at the following link: https://docs.
microsoft.com/en-us/windows/uwp/design/style/reveal
1. Navigate to Start | Settings | Update & Security | For developers, and then click on
Developer mode.
2. Accept the warning about how it "could expose your device and personal data to
security risk or harm your device," and then close the Settings app.
Good Practice: Since the Fluent Design System was first released with
Window 10 Fall Creators Update (10.0; Build 16299), you should be
able to select that to support the features that we will cover in this
appendix, but while you're learning, it's best to use the latest version
to avoid unexpected incompatibilities. Developers writing UWP
apps for a general audience should choose one of the latest builds of
Windows 10 for Minimum Version. Developers writing enterprise
apps should choose an older Minimum Version. Build 10240 was
released in July 2015 and is a good choice for maximum compatibility,
but you will not have access to modern features such as Fluent Design
System.
6. In Solution Explorer, double-click on the MainPage.xaml file to open it for editing. You
will see the XAML design window showing a graphical view and a XAML view. You
will be able to make the following observations:
• The XAML designer is split horizontally, but you can toggle to a vertical split
and collapse one side by clicking on the buttons on the right edge of the divider.
• You can swap views by clicking on the double-arrow button in the divider.
Building Windows Desktop Apps
7. For Design view, change the device to 13.3" Desktop (1280 x 720) 100% scale and zoom
to 100%.
8. Navigate to View | Toolbox or press Ctrl + W, X. Note that the toolbox has sections for
Common XAML Controls, All XAML Controls, and General.
9. At the top of the toolbox is a search box. Enter the letters bu, and then note that the list
of controls is filtered.
10. Drag and drop the Button control from the toolbox onto the Design view.
11. Resize it by clicking, holding, and dragging any of the eight square-shape resize
handles on each edge and in each corner.
Note that the button is given a fixed width and height, and fixed left (30 units) and top
(40 units) margins, to position and size it absolutely inside the grid, as shown in the
following screenshot:
Appendix B
Although you can drag and drop controls, it is better to use the XAML view for layout
so that you can position items relatively and implement more of a responsive design.
12. In the XAML view, find the Button element and delete it.
13. In the XAML view, inside the Grid element, enter the following markup:
<Button Margin="6" Padding="6" Name="ClickMeButton">
Click Me
</Button>
14. Change the zoom to 50% and note that the button is automatically sized to its content,
Click Me, aligned vertically in the center and aligned horizontally to the left, even if
you toggle between vertical and horizontal phone layouts.
15. In the XAML view, delete the Grid element, and modify the XAML to wrap the Button
element inside a horizontally orientated StackPanel with a light gray background
that is inside a vertically orientated (by default) StackPanel, and note the change in its
layout to be in the top left of the available space, as shown in the following code:
<StackPanel>
<StackPanel Orientation="Horizontal" Padding="4"
Background="LightGray" Name="toolbar">
<Button Margin="6" Padding="6" Name="ClickMeButton">
Click Me
</Button>
</StackPanel>
</StackPanel>
16. Modify the Button element to give it a new event handler for its Click event, as shown
in the following screenshot:
17. Right-click the event handler name and select Go To Definition or press F12.
Building Windows Desktop Apps
18. Add a statement to the event handler method that sets the content of the button to the
current time, as shown in the following code:
private void ClickMeButton_Click(object sender, RoutedEventArgs e)
{
ClickMeButton.Content = DateTime.Now.ToString("hh:mm:ss");
}
19. Navigate to Build | Configuration Manager... for the FluentUwpApp project, select
the Build and Deploy checkboxes, select a Platform of x64, and then select Close, as
shown in the following screenshot:
20. Run the application by navigating to Debug | Start Without Debugging or pressing
Ctrl + F5.
21. Click on the Click Me button and note that every time you click on the button, the
button's content changes to show the current time.
1. Open MainPage.xaml, set the stack panel's background to use the acrylic system window
brush, and add some elements to the stack panel after the button for the user to enter
their name, as shown highlighted in the following markup:
Appendix B
<StackPanel
Background="{ThemeResource SystemControlAcrylicWindowBrush}">
<StackPanel Orientation="Horizontal" Padding="4"
Background="LightGray" Name="toolbar">
<Button Margin="6" Padding="6" Name="ClickMeButton"
Click="ClickMeButton_Click">
Click Me
</Button>
<TextBlock Text="First name:"
VerticalAlignment="Center" Margin="4" />
<TextBox PlaceholderText="Enter your name"
VerticalAlignment="Center" Width="200" />
</StackPanel>
</StackPanel>
2. Run the application by navigating to Debug | Start Without Debugging, and note the
tinted acrylic material showing the green tent and orange sunset over the mountains of
one of the standard Windows 10 wallpapers through the app window background, as
shown in the following screenshot:
Acrylic uses a lot of system resources, so if an app loses focus, or your device is low on battery,
then acrylic is disabled automatically.
Exploring Reveal
Reveal is built-in for some controls, such as ListView and NavigationView, that you will see
later. For other controls, you can enable it by applying a theme style. First, we will add some
XAML to define a calculator user interface made up of a grid of buttons. Then, we will add an
event handler for the page's Loaded event so that we can apply the Reveal theme style and other
properties by enumerating the buttons instead of having to manually set attributes for each one
in XAML:
Building Windows Desktop Apps
1. Open MainPage.xaml, add a new horizontal stack panel under the one used as a
toolbar, and add a grid with buttons to define a calculator, as shown highlighted in the
following markup:
<StackPanel
Background="{ThemeResource SystemControlAcrylicWindowBrush}">
<StackPanel Orientation="Horizontal" Padding="4"
Background="LightGray" Name="toolbar">
<Button Margin="6" Padding="6" Name="ClickMeButton"
Click="ClickMeButton_Click">
Click Me
</Button>
<TextBlock Text="First name:"
VerticalAlignment="Center" Margin="4" />
<TextBox PlaceholderText="Enter your name"
VerticalAlignment="Center" Width="200" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<Grid Background="DarkGray" Margin="10"
Padding="5" Name="gridCalculator">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Button Grid.Row="0" Grid.Column="0" Content="X" />
<Button Grid.Row="0" Grid.Column="1" Content="/" />
<Button Grid.Row="0" Grid.Column="2" Content="+" />
<Button Grid.Row="0" Grid.Column="3" Content="-" />
<Button Grid.Row="1" Grid.Column="0" Content="7" />
<Button Grid.Row="1" Grid.Column="1" Content="8" />
<Button Grid.Row="1" Grid.Column="2" Content="9" />
<Button Grid.Row="1" Grid.Column="3" Content="0" />
<Button Grid.Row="2" Grid.Column="0" Content="4" />
Appendix B
2. In the Page element, add a new event handler for Loaded, as shown highlighted in the
following markup:
<Page
...
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
Loaded="Page_Loaded">
5. Run the application by navigating to Debug | Start Without Debugging and note the
calculator buttons start with a flat gray user interface.
Building Windows Desktop Apps
6. When the user moves their mouse pointer over the bottom-right corner of the 8 button,
we see that Reveal lights it up, and parts of the surrounding buttons light up too, as
shown in the following screenshot:
The implementation of the Reveal effect has subtlety changed over the recent biannual updates
to Windows 10, so the effect in your app may look slightly different.
More Information: You can read more about the UWP Community Toolkit
at the following link: https://docs.microsoft.com/en-us/windows/
communitytoolkit/
More Information: You can read about the Markdown project at the following
link: https://daringfireball.net/projects/markdown/
Let's install the UWP Community Toolkit now and explore some of its controls:
6. Inside the second horizontal stack panel and after the calculator grid, add a textbox
and a markdown text block that are data bound together so that the text in the textbox
becomes the source of the markdown control, as shown highlighted in the following
markup:
<StackPanel Orientation="Horizontal">
<Grid Background="DarkGray" Margin="10"
Padding="5" Name="gridCalculator">
...
</Grid>
<TextBox Name="markdownSource" Text="# Welcome"
Header="Enter some Markdown text:"
VerticalAlignment="Stretch" Margin="5"
AcceptsReturn="True" />
<kit:MarkdownTextBlock Margin="5"
Text="{Binding ElementName=markdownSource, Path=Text}"
VerticalAlignment="Stretch" HorizontalAlignment="Stretch" />
</StackPanel>
7. Run the application by navigating to Debug | Start Without Debugging and note that
the user can enter Markdown syntax in the textbox, and it is rendered in the Markdown
text block, as shown in the following screenshot:
Building Windows Desktop Apps
Sharing resources
A good place to define shared resources is at the app level, so let's see how to do that:
<Application.Resources>
<LinearGradientBrush x:Key="rainbow">
<GradientStop Color="Red" Offset="0" />
<GradientStop Color="Orange" Offset="0.1" />
<GradientStop Color="Yellow" Offset="0.3" />
<GradientStop Color="Green" Offset="0.5" />
<GradientStop Color="Blue" Offset="0.7" />
<GradientStop Color="Indigo" Offset="0.9" />
<GradientStop Color="Violet" Offset="1" />
</LinearGradientBrush>
</Application.Resources>
</Application>
5. As you enter the reference to a static resource, IntelliSense will show your rainbow
resource and the built-in resources, as shown in the following screenshot:
Appendix B
Resources can be defined and stored inside any element of XAML, not just at the app level. For
example, if a resource is only needed on MainPage, then it can be defined there. You can also
dynamically load XAML files at runtime.
More Information: You can read more about the Resource Management
System at the following link: https://docs.microsoft.com/en-us/
windows/uwp/app-resources/
One of the most common resources is a style that can set multiple properties at once. If a style
has a unique key, then it must be explicitly set, as we did earlier with the linear gradient. If it
doesn't have a key, then it will be automatically applied based on the TargetType property:
Building Windows Desktop Apps
<Setter Property="Template"
Value="{StaticResource DarkGlassButton}" />
<Setter Property="Foreground" Value="White" />
</Style>
</Application.Resources>
2. Run the application and note the black glass effect on the button in the toolbar.
The calculator buttons are not affected at runtime by this black glass effect because we replace
their styles using code after the page has loaded.
Binding to elements
The simplest type of binding is between elements:
1. In MainPage.xaml, after the second horizontal stack panel and inside the outer vertical
stack panel, add a text block for instructions, a slider for selecting a rotation, a grid
containing a stack panel and text blocks to show the selected rotation in degrees, a
radial gauge from the UWP Community Toolkit, and a red square to rotate, as shown in
the following markup:
<TextBlock Margin="10">
Use the slider to rotate the square:
</TextBlock>
<Slider Value="180" Minimum="0" Maximum="360"
Name="sliderRotation" Margin="10,0" />
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<StackPanel Orientation="Horizontal"
VerticalAlignment="Center"
HorizontalAlignment="Center">
<TextBlock FontSize="30"
Text="{Binding ElementName=sliderRotation, Path=Value}" />
<TextBlock Text="degrees" FontSize="30" Margin="10,0" />
</StackPanel>
<kit:RadialGauge Grid.Column="1" Minimum="0" Maximum="360"
Value="{Binding ElementName=sliderRotation, Path=Value}"
Building Windows Desktop Apps
2. Note that the text of the text block, the value of the radial gauge, and the angle of the
rotation transform are all bound to the slider's value using the {Binding} markup
extension that's specific to the name of the element and the name, also known as the
path, of a property to bind to.
3. Run the app and then click, hold, and drag the slider to rotate the red square, as shown
in the following screenshot:
1. .NET 5 is cross-platform. Windows Forms and WPF apps can run on .NET 5. Can those
apps therefore run on macOS and Linux?
2. How does a Windows Forms app define its user interface and why is this a potential
problem?
3. How can a WPF or UWP app define its user interface and why is this good for
developers?
4. List five layout containers and how their child elements are positioned within them.
5. What is the difference between Margin and Padding for an element like a Button?
6. How are event handlers attached to an object using XAML?
7. What do XAML styles do?
8. Where can you define resources?
9. How can you bind the property of one element to a property on another element?
10. Why might you implement IValueConverter?
Summary
In this appendix, you learned that .NET 5 supports older technologies for building Windows
desktop applications, including Windows Forms and WPF.
You learned how to build a graphical user interface using XAML and the new Fluent Design
System, including features such as acrylic material and Reveal lighting.
You also learned how to share resources in an app, how to replace a control's template, and
how to bind to data and controls.