
- •Table of Contents
- •About the Author
- •About the Technical Reviewer
- •Acknowledgments
- •Introduction
- •Installing Visual Studio
- •Visual Studio 2022 System Requirements
- •Operating Systems
- •Hardware
- •Supported Languages
- •Additional Notes
- •Visual Studio Is 64-Bit
- •Full .NET 6.0 Support
- •Using Workloads
- •The Solution Explorer
- •Toolbox
- •The Code Editor
- •New Razor Editor
- •What’s Available?
- •Hot Reload
- •Navigating Code
- •Navigate Forward and Backward Commands
- •Navigation Bar
- •Find All References
- •Find Files Faster
- •Reference Highlighting
- •Peek Definition
- •Subword Navigation
- •Features and Productivity Tips
- •Track Active Item in Solution Explorer
- •Hidden Editor Context Menu
- •Open in File Explorer
- •Finding Keyboard Shortcut Mappings
- •Clipboard History
- •Go To Window
- •Navigate to Last Edit Location
- •Multi-caret Editing
- •Sync Namespaces to Match Your Folder Structure
- •Paste JSON As Classes
- •Enable Code Cleanup on Save
- •Add Missing Using on Paste
- •Features in Visual Studio 2022
- •Visual Studio Search
- •Solution Filters
- •Visual Studio IntelliCode
- •Whole Line Completions
- •Visual Studio Live Share
- •Summary
- •Visual Studio Project Types
- •Various Project Templates
- •Console Applications
- •Windows Forms Application
- •Windows Service
- •Web Applications
- •Class Library
- •MAUI
- •Creating a MAUI Application
- •Pairing to Mac for iOS Development
- •Consuming REST Services in MAUI
- •The Complete Weather App
- •The Target Platforms
- •The Required NuGet Package
- •The Weather Models
- •The WeatherService
- •The MainViewModel
- •Registering Dependencies
- •Building the MainPage View
- •Using SQLite in a MAUI Application
- •The ToDoItem Model
- •The ToDoService
- •The MainViewModel
- •Registering Dependencies
- •Building the MainPage View
- •Managing NuGet Packages
- •Using NuGet in Visual Studio
- •Hosting Your Own NuGet Feeds
- •Managing nmp Packages
- •Creating Project Templates
- •Creating and Using Code Snippets
- •Creating Code Snippets
- •Using Bookmarks and Code Shortcuts
- •Bookmarks
- •Code Shortcuts
- •Adding Custom Tokens
- •The Server Explorer
- •Running SQL Queries
- •Visual Studio Windows
- •C# Interactive
- •Code Metrics Results
- •Maintainability Index
- •Cyclomatic Complexity
- •Class Coupling
- •Send Feedback
- •Personalizing Visual Studio
- •Adjust Line Spacing
- •Document Management Customizations
- •The Document Close Button
- •Modify the Dirty Indicator
- •Show Invisible Tabs in Italics in the Tab Drop-Down
- •Colorize Document Tabs
- •Tab Placement
- •Visual Studio Themes
- •Summary
- •Setting a Breakpoint
- •Step into Specific
- •Run to Click
- •Run to Cursor
- •Force Run to Cursor
- •Conditional Breakpoints and Actions
- •Temporary Breakpoints
- •Dependent Breakpoints
- •Dragging Breakpoints
- •Manage Breakpoints with Labels
- •Exporting Breakpoints
- •Using DataTips
- •Visualizing Complex Data Types
- •Bonus Tip
- •Using the Watch Window
- •The DebuggerDisplay Attribute
- •Evaluate Functions Without Side Effects
- •Format Specifiers
- •dynamic
- •hidden
- •results
- •Diagnostic Tools
- •CPU Usage
- •Memory Usage
- •The Events View
- •The Right Tool for the Right Project Type
- •Immediate Window
- •Attaching to a Running Process
- •Attach to a Remote Process
- •Remote Debugger Port Assignments
- •Remote Debugging
- •System Requirements
- •Download and Install Remote Tools
- •Running Remote Tools
- •Start Remote Debugging
- •Summary
- •Creating and Running Unit Tests
- •Create and Run a Test Playlist
- •Testing Timeouts
- •Using Live Unit Tests
- •Using IntelliTest to Generate Unit Tests
- •Focus IntelliTest Code Exploration
- •How to Measure Code Coverage in Visual Studio
- •Summary
- •Create a GitHub Account
- •Create and Clone a Repository
- •Create a Branch from Your Code
- •Creating and Handling Pull Requests
- •Multi-repo Support
- •Compare Branches
- •Check Out Commit
- •Line Staging
- •Summary
- •Index
Chapter 2 Working with Visual Studio 2022
As seen in Listing 2-13, the service is really straightforward. By adding the SQLite namespace via the using statement, we can create a SQLiteAsyncConnection object that accepts a path to the database file called mydb.db. The Init method checks to see if the database exists and, if not, creates the database with the todo table from the ToDoItem. Because the SQLite connection is asynchronous, we can call the InsertAsync and ToListAsync methods to insert and get to-do items.
The MainViewModel
The MainViewModel provides an ObservableCollection of ToDoItem and creates an ObservableProperty for the isRefreshing field, as seen in Listing 2-14. This way, if the collection of to-do items is busy being refreshed, we can control that if the user clicks the refresh button multiple times.
Listing 2-14. The MainViewModel Class
using System.Collections.ObjectModel; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input;
using HelloMAUI.Model; using HelloMAUI.Services;
namespace HelloMAUI.ViewModel
{
public partial class MainViewModel : ObservableObject
{
readonly IToDoService _service;
public ObservableCollection<ToDoItem> ToDoItems { get; set; } = new();
[ObservableProperty] bool isRefreshing;
public MainViewModel(IToDoService service)
{
_service = service;
}
101
Chapter 2 Working with Visual Studio 2022
[RelayCommand] async Task AddTodo()
{
var item = await Application.Current.MainPage.Display PromptAsync("To Do Item", "Enter To-Do Item.", "Add", "Cancel"); if (item != null)
{
await _service.AddToDo(item); await Refresh();
}
}
[RelayCommand]
async Task GetAllTodoItems()
{
if (IsRefreshing) return;
var todoItems = await _service.GetToDoItems();
if (todoItems.Count() > 0) ToDoItems.Clear();
foreach (var item in todoItems)
{
var todo = new ToDoItem()
{
ToDoText = item.ToDoText, Id = item.Id
};
ToDoItems.Add(todo);
}
}
[RelayCommand] async Task Refresh()
{
102
Chapter 2 Working with Visual Studio 2022
if (!IsRefreshing)
{
IsRefreshing = true; ToDoItems.Clear();
var todoItems = await _service.GetToDoItems();
foreach (var item in todoItems)
{
var todo = new ToDoItem()
{
ToDoText = item.ToDoText, Id = item.Id
};
ToDoItems.Add(todo);
}
IsRefreshing = false;
}
}
}
}
Again, the code in the view model is relatively straightforward. We use dependency injection to inject our ToDo Service via the constructor. We then set up the methods to add to-do items, read to-do items, and refresh the to-do items to act as commands by adding the [RelayCommand] attribute to each one. These allow us to use our ToDo Service to add and read items from SQLite. The last thing we need to do is register the service dependencies with the IServiceCollection.
Registering Dependencies
The services are registered in the MauiProgram class by adding them as Singletons to the IServiceCollection, as seen in Listing 2-15.
103
Chapter 2 Working with Visual Studio 2022
Listing 2-15. Registering the Services
using HelloMAUI.Services; using HelloMAUI.ViewModel;
namespace HelloMAUI;
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder(); builder
.UseMauiApp<App>()
.ConfigureFonts(fonts =>
{
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular"); fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
});
builder.Services.AddSingleton<IToDoService, ToDoService>(); builder.Services.AddSingleton<MainViewModel>(); builder.Services.AddSingleton<MainPage>();
return builder.Build();
}
}
We are telling our application that whenever something requests IToDoService, give it the ToDoService class that contains the implementation for our IToDoService
Interface. This loose coupling allows us to easily swap out the implementation contained in the ToDoService class and replace it with another implementation. We have now registered our page (MainPage), our view model (MainViewModel), and our to-do service (IToDoService) with the IServiceCollection. We can now go ahead and start building the UI for our application.
104