我正在构建一个 MAUI 应用程序,并试图找出在打开/重新打开 XAML 页面时从互联网获取数据的正确且推荐的方法。
我找到了使用代码隐藏方法的建议:
protected override void OnAppearing()
{
base.OnAppearing();
// Code to execute when the page appears
}
protected override void OnDisappearing()
{
base.OnDisappearing();
// Code to execute when the page disappears
}
...但我想在我的页面的 ViewModel 中执行此操作。什么才是正确的做法?
您可以尝试通过为您的应用创建
BaseViewModel
和 BasePage
来实现此目的。
请按照以下步骤操作:
1.安装nuget CommunityToolkit.MVVM
2.创建类
BasePage
如下:
public class BasePage : ContentPage
{
public BasePage()
{
NavigationPage.SetBackButtonTitle(this, "Back");
Loaded += OnLoaded;
Unloaded += OnUnloaded;
}
void OnLoaded(object sender, EventArgs e)
{
SetupBinding(BindingContext);
}
void OnUnloaded(object sender, EventArgs e)
{
TearDownBinding(BindingContext);
}
protected void SetupBinding(object bindingContext)
{
if (bindingContext is BaseViewModel vm)
{
vm.DoDisplayAlert += OnDisplayAlert;
vm.DoNavigate += OnNavigate;
vm.OnAppearing();
}
}
protected void TearDownBinding(object bindingContext)
{
if (bindingContext is BaseViewModel vm)
{
vm.OnDisappearing();
vm.DoDisplayAlert -= OnDisplayAlert;
vm.DoNavigate -= OnNavigate;
}
}
Task OnDisplayAlert(string message)
{
return DisplayAlert(Title, message, "OK");
}
Task OnNavigate(BaseViewModel vm, bool showModal)
{
var name = vm.GetType().Name;
name = name.Replace("ViewModel", "Page", StringComparison.Ordinal);
var ns = GetType().Namespace;
var pageType = Type.GetType($"{ns}.{name}");
var page = (BasePage)Activator.CreateInstance(pageType);
page.BindingContext = vm;
return showModal
? Navigation.PushModalAsync(page)
: Navigation.PushAsync(page);
}
}
3.创建
BaseViewModel.cs
,如下:
public class BaseViewModel: ObservableObject
{
/* bool isBusy;
public bool IsBusy
{
get => isBusy;
set => SetProperty(ref isBusy, value, onChanged: () => OnPropertyChanged(nameof(IsNotBusy)));
}*/
public virtual void OnAppearing()
{
}
public virtual void OnDisappearing()
{
}
internal event Func<string, Task> DoDisplayAlert;
internal event Func<BaseViewModel, bool, Task> DoNavigate;
public Task DisplayAlertAsync(string message)
{
return DoDisplayAlert?.Invoke(message) ?? Task.CompletedTask;
}
public Task NavigateAsync(BaseViewModel vm, bool showModal = false)
{
return DoNavigate?.Invoke(vm, showModal) ?? Task.CompletedTask;
}
}
3.创建
TestViewModel.cs
public class TestViewModel:BaseViewModel
{
public override void OnAppearing()
{
System.Diagnostics.Debug.WriteLine("-------do something when the page appears");
base.OnAppearing();
}
public override void OnDisappearing()
{
System.Diagnostics.Debug.WriteLine("-------do something when the page disappears");
base.OnDisappearing();
}
}
4.创建一个扩展
TestPage.xaml
的 BasePage
并将此页面的 BindingContext
设置为 TestViewModel.cs
。
<?xml version="1.0" encoding="utf-8" ?>
<views:BasePage
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:views="clr-namespace:MauiApp129.Pages"
xmlns:viewmodels="clr-namespace:MauiApp129.ViewModels"
Title="TestPage"
x:Class="MauiApp129.Pages.TestPage"
>
<views:BasePage.BindingContext>
<viewmodels:TestViewModel></viewmodels:TestViewModel>
</views:BasePage.BindingContext>
<VerticalStackLayout>
<Label
Text="Welcome to .NET MAUI!"
VerticalOptions="Center"
HorizontalOptions="Center" />
</VerticalStackLayout>
</views:BasePage>
TestPage.xaml.cs
public partial class TestPage : BasePage
{
public TestPage()
{
InitializeComponent();
}
}
5.如果您想导航到
TestPage
,您可以使用以下代码:
private async void Button_Clicked(object sender, EventArgs e)
{
await Navigation.PushAsync((Page)Activator.CreateInstance(typeof(TestPage)));
}
注:
您也可以参考官方示例:.NET MAUI - 平台集成,其中也使用了
BasePage
和BaseViewModel
这种方式。