author | ms.author | ms.date | ms.topic | no-loc | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
adegeo |
adegeo |
03/20/2024 |
include |
|
This portion of the tutorial adds the final piece of the app, a view that displays all of the notes previously created.
Currently the note view displays a single note. To display multiple notes, create a new view and model: AllNotes.
- In the Solution Explorer pane, right-click on the :::no-loc text="Views"::: folder and select Add > New Item...
- In the Add New Item dialog, select .NET MAUI in the template list on the left-side of the window. Next, select the .NET MAUI ContentPage (XAML) template. Name the file AllNotesPage.xaml, and then select Add.
- In the Solution Explorer pane, right-click on the :::no-loc text="Models"::: folder and select Add > Class...
- Name the class AllNotes.cs and press Add.
The new model will represent the data required to display multiple notes. This data will be a property that represents a collection of notes. The collection will be an ObservableCollection
which is a specialized collection. When a control lists multiple items, such as a xref:Microsoft.Maui.Controls.ListView, is bound to an ObservableCollection
, the two work together to automatically keep the list of items in sync with the collection. If the list adds an item, the collection is updated. If the collection adds an item, the control is automatically updated with a new item.
-
In the Solution Explorer pane, open the Models\AllNotes.cs file.
-
Replace the code with the following snippet:
:::code language="csharp" source="../snippets/allnotes/Models/AllNotes.cs":::
The previous code declares a collection, named Notes
, and uses the LoadNotes
method to load notes from the device. This method uses LINQ extensions to load, transform, and sort the data into the Notes
collection.
Next, the view needs to be designed to support the AllNotes model.
-
In the Solution Explorer pane, open the Views\AllNotesPage.xaml file.
-
Replace the code with the following markup:
:::code language="xaml" source="../snippets/allnotes/Views/AllNotesPage.xaml":::
The previous XAML introduces a few new concepts:
-
The
ContentPage.ToolbarItems
property contains aToolbarItem
. The buttons defined here are usually display at the top of the app, along the page title. Depending on the platform, though, it may be in a different position. When one of these buttons is pressed, theClicked
event is raised, just like a normal button.The
ToolbarItem.IconImageSource
property sets the icon to display on the button. The icon can be any image resource defined by the project, however, in this example, aFontImage
is used. AFontImage
can use a single glyph from a font as an image. -
The xref:Microsoft.Maui.Controls.CollectionView control displays a collection of items, and in this case, is bound to the model's
Notes
property. The way each item is presented by the collection view is set through theCollectionView.ItemsLayout
andCollectionView.ItemTemplate
properties.For each item in the collection, the
CollectionView.ItemTemplate
generates the declared XAML. TheBindingContext
of that XAML becomes the collection item itself, in this case, each individual note. The template for the note uses two labels, which are bound to the note'sText
andDate
properties. -
The xref:Microsoft.Maui.Controls.CollectionView handles the
SelectionChanged
event, which is raised when an item in the collection view is selected.
The code-behind for the view needs to be written to load the notes and handle the events.
-
In the Solution Explorer pane, open the Views/AllNotesPage.xaml.cs file.
-
Replace the code with the following snippet:
:::code language="csharp" source="../snippets/allnotes/Views/AllNotesPage.xaml.cs":::
This code uses the constructor to set the BindingContext
of the page to the model.
The OnAppearing
method is overridden from the base class. This method is automatically called whenever the page is shown, such as when the page is navigated to. The code here tells the model to load the notes. Because the xref:Microsoft.Maui.Controls.CollectionView in the AllNotes view is bound to the AllNotes model's Notes
property, which is an ObservableCollection
, whenever the notes are loaded, the xref:Microsoft.Maui.Controls.CollectionView is automatically updated.
The Add_Clicked
handler introduces another new concept, navigation. Because the app is using .NET MAUI Shell, you can navigate to pages by calling the Shell.Current.GoToAsync
method. Notice that the handler is declared with the async
keyword, which allows the use of the await
keyword when navigating. This handler navigates to the NotePage
.
The last piece of code in the previous snippet is the notesCollection_SelectionChanged
handler. This method takes the currently selected item, a :::no-loc text="Note"::: model, and uses its information to navigate to the NotePage
. xref:Microsoft.Maui.Controls.Shell.GoToAsync%2A uses a URI string for navigation. In this case, a string is constructed that uses a query string parameter to set a property on the destination page. The interpolated string representing the URI ends up looking similar to the following string:
NotePage?ItemId=path\on\device\XYZ.notes.txt
The ItemId=
parameter is set to the file name on the device where the note is stored.
Visual Studio may be indicating that the NotePage.ItemId
property doesn't exist, which it doesn't. The next step is modifying the :::no-loc text="Note"::: view to load the model based on the ItemId
parameter that you'll create.
The :::no-loc text="Note"::: view needs to support the query string parameter, ItemId
. Create it now:
-
In the Solution Explorer pane, open the Views/NotePage.xaml.cs file.
-
Add the
QueryProperty
attribute to theclass
keyword, providing the name of the query string property, and the class property it maps to,ItemId
andItemId
respectively::::code language="csharp" source="../snippets/allnotes/Views/NotePage.xaml.cs" id="query_prop":::
-
Add a new
string
property namedItemId
. This property calls theLoadNote
method, passing the value of the property, which in turn, should be the file name of the note::::code language="csharp" source="../snippets/allnotes/Views/NotePage.xaml.cs" id="itemid":::
-
Replace the
SaveButton_Clicked
andDeleteButton_Clicked
handlers with the following code::::code language="csharp" source="../snippets/allnotes/Views/NotePage.xaml.cs" id="buttons":::
The buttons are now
async
. After they're pressed, the page navigates back to the previous page by using a URI of..
. -
Delete the
_fileName
variable from top of the code, as it's no longer used by the class.
The AppShell
is still loading the single note page, instead, it needs to load the AllPages view. Open the AppShell.xaml file and change the first xref:Microsoft.Maui.Controls.ShellContent entry to point to the AllNotesPage
instead of NotePage
:
:::code language="xaml" source="../snippets/allnotes/AppShell.xaml" highlight="12":::
If you run the app now, you'll notice it crashes if you press the Add button, complaining that it can't navigate to NotesPage
. Every page that can be navigated to from another page, needs to be registered with the navigation system. The AllNotesPage
and AboutPage
pages are automatically registered with the navigation system by being declared in the xref:Microsoft.Maui.Controls.TabBar.
Register the NotesPage
with the navigation system:
-
In the Solution Explorer pane, open the AppShell.xaml.cs file.
-
Add a line to the constructor that registers the navigation route:
:::code language="csharp" source="../snippets/allnotes/AppShell.xaml.cs" highlight="9":::
The Routing.RegisterRoute
method takes two parameters:
- The first parameter is the string name of the URI you want to register, in this case the resolved name is
"NotePage"
. - The second parameter is the type of page to load when
"NotePage"
is navigated to.
Now you can run your app. Try adding new notes, navigating back and forth between notes, and deleting notes.
Explore the code for this tutorial.. If you want to download a copy of the completed project to compare your code with, download this project.