Рассмотрим, как мы можем передавать данные из одной страницы в другую. Здесь могут быть различные варианты. Наиболее распространенный способ представляет передача данных через конструктор.
Например, пусть у нас есть две страницы:
class PageA : ContentPage { public PageA() { //........ } } class PageB : ContentPage { public PageB(int x) { //............ } }
Страница PageB в конструкторе в качестве параметра принимает некоторое число, и чтобы перейти на нее из страницы PageA, мы могли бы использовать следующее выражение:
await Navigation.PushAsync(new PageB(56));
Другой вариант состоит в использовании методов или свойств второй страницы для передачи в нее данных. Например, пусть в PageB определен некий метод, принимающий в качестве параметра число:
class PageB : ContentPage { public void Calculate(int x) { } }
Тогда передать данные в этот метод из PageA мы могли бы следующим способом:
PageB pageB = new PageB(); await Navigation.PushAsync(pageB); pageB.Calculate(56);
Теперь рассмотрим на реальном примере. Вначале добавим в проект класс Person, с объектами которого мы будем работать в программе:
using System.ComponentModel; using System.Runtime.CompilerServices; namespace HelloApp; public class Person : INotifyPropertyChanged { string name = ""; int age; public event PropertyChangedEventHandler? PropertyChanged; public string Name { get => name; set { if (name != value) { name = value; OnPropertyChanged(); } } } public int Age { get => age; set { if (age != value) { age = value; OnPropertyChanged(); } } } public void OnPropertyChanged([CallerMemberName] string prop = "") { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(prop)); } }
Важно, что этот класс реализует интерфейс INotifyPropertyChanged, что даст возможность элементам пользовательского интерфейса автоматически синхронизировать значения со значениями свойств объекта Person.
Далее добавим в проект новую страницу по типу Content Page, которую назовем PersonPage:
В XAML-коде главной страницы MainPage определим следующий интерфейс:
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="HelloApp.MainPage" xmlns:local="clr-namespace:HelloApp" Title="Список пользователей"> <StackLayout> <Button Text="Добавить" Clicked="AddButton_Click" /> <ListView x:Name="peopleList" ItemsSource="{Binding}" ItemSelected="OnListViewItemSelected"> <ListView.Header> <Grid BackgroundColor="#ddd"> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <Label Text="Имя" FontSize="16" Grid.Column="0" /> <Label Text="Возраст" FontSize="16" Grid.Column="1" /> </Grid> </ListView.Header> <ListView.ItemTemplate> <DataTemplate> <ViewCell> <ViewCell.View> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <Label Text="{Binding Name}" FontSize="16" Grid.Column="0" /> <Label Text="{Binding Age}" FontSize="15" Grid.Column="1" /> </Grid> </ViewCell.View> </ViewCell> </DataTemplate> </ListView.ItemTemplate> </ListView> </StackLayout> </ContentPage>
Здесь в ListView будет выводиться список объектов Person. По нажатию на кнопку будет открываться форма для добавления нового элемента, а в результате выбора элемента в списке ListView выбранный элемент будет передаваться на ту же форму для редактирования.
И в коде c# у MainPage определим обработчики кнопок и выделения списка:
using System.Collections.ObjectModel; namespace HelloApp; public partial class MainPage : ContentPage { ObservableCollection<Person> People { get; set; } public MainPage() { InitializeComponent(); People = new ObservableCollection<Person> { new Person {Name="Tom", Age = 38}, new Person {Name="Bob", Age = 42}, new Person {Name="Sam", Age = 25}, }; peopleList.BindingContext = People; } // обработчик выбора элемента в списке async void OnListViewItemSelected(object sender, SelectedItemChangedEventArgs args) { // Получаем выбранный элемент if (args.SelectedItem is Person selectedPerson) { // Снимаем выделение peopleList.SelectedItem = null; // Переходим на страницу редактирования элемента await Navigation.PushAsync(new PersonPage(selectedPerson)); } } // переходим на страницу PersonPage для добавления нового элемента async void AddButton_Click(object sender, EventArgs e) { await Navigation.PushAsync(new PersonPage(null)); } // вспомогательный метод для добавления элемента в список protected internal void AddPerson(Person phone) { People.Add(phone); } }
На странице PersonPage в xaml определим следующий код:
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="HelloApp.PersonPage" Title="Информация о пользователе"> <StackLayout> <Entry x:Name="nameEntry" Text="{Binding Path=Name}" /> <StackLayout Orientation="Horizontal"> <Stepper x:Name="ageStepper" Minimum="0" Maximum="110" Increment="1" Value="{Binding Path=Age}"/> <Label x:Name="ageLbl" FontSize="18" Text="{Binding Source={x:Reference Name=ageStepper}, Path=Value }" /> </StackLayout> <Button Text="Сохранить" Clicked="SavePerson" /> </StackLayout> </ContentPage>
А в файле кода C# для PersonPage следующие строки:
namespace HelloApp; public partial class PersonPage : ContentPage { bool edited = true; // флаг редактирования // добавляемый/редактируемый пользователь Person Person { get; set; } public PersonPage(Person? person) { InitializeComponent(); if (person is null) { Person = new Person(); edited = false; } else { Person = person; } BindingContext = Person; } async void SavePerson(object sender, EventArgs e) { await Navigation.PopAsync(); // если добавление if (edited == false) { if(Application.Current?.MainPage is NavigationPage navPage) { // стек навигации IReadOnlyList<Page> navStack = navPage.Navigation.NavigationStack; // количество страниц в стеке int pageCount = navPage.Navigation.NavigationStack.Count; // находим в стеке предыдущую страницу - то есть MainPage if (navStack[pageCount - 1] is MainPage mainPage) { // вызываем у главной страницы метод AddPerson для добавления mainPage.AddPerson(Person); } } } } }
Для разграничения ситуаций добавления и редактирования здесь определена дополнительная переменная edited
. Если в конструктор страницы передается
объек Person, то эта переменная равна true
. Если же в конструктор передается значение null, то переменная равна false
, и создается новый
объект Person.
В обработчике кнопки SavePerson()
, если у нас редактирование, то мы просто возвращаемся назад на предыдущую страницу. Поскольку редактируемый
объект Person реализует интерфейс INotifyPropertyChanged, то нам не надо выполнять никаких дополнительных действий, и соответствующий объект на главной станице MainPage будет сам автоматически
обновлен.
Если же у нас добавление, то получаем из стека навигации страницу MainPage и вызываем у нее метод AddPerson()
для добавления объекта. Стоит
также заметить, что на странице MainPage привязка списка идет не к простому списку List, а к объекту ObservableCollection, что позволяет автоматически обновить
привязанный объект ListView в случае добавления нового объекта.
Запустим проект, и на странице отобразится список объектов. Мы можем нажать на кнопку добавления, и произодейт переход к странице PersonPage, где можно добавить новый объект:
Подобным образом можно выберать какой-либо объект, и он будет передан на страницу PersonPage.