使用视图模型并在ContentView中调用OnAppearing



我在Xamarin Forms 5应用程序中使用ContentPage的视图模型,通常在视图模型中从代码背后的OnAppearing()方法调用Init()方法。

我在ContentView中尝试了同样的方法,但它从未达到OnAppearing()方法。

这是我的ContentView代码:

<ContentView xmlns="http://xamarin.com/schemas/2014/forms" 
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:vm="clr-namespace:MyApp.ViewModels"
x:Class="MyApp.MyContentView">
<ContentView.BindingContext>
<vm:MyViewModel/>
</ContentView.BindingContext>
<ContentView.Content>
<StackLayout
BackgroundColor="{StaticResource PrimaryDark }"
HeightRequest="200">
<Label
Text="{Binding User.FullName}"
TextColor="White"
FontSize="Medium"
FontAttributes="Bold"
HorizontalOptions="CenterAndExpand"/>
</StackLayout>
</ContentView.Content>
</ContentView>

此内容视图的视图模型如下所示:

public class MyViewModel : BaseViewModel
{
User user;
public MyViewModel()
{
}
public User User
{
get => user;
set
{
if (user == value)
return;
user = value;
OnPropertyChanged();
}
}
public async void Init()
{
// Get user info
var data = await _dbService.GetUser();
if(data != null)
{
User = data;
OnPropertyChanged(nameof(User));
}
}
}

在我的代码后面,这就是我正在做的:

public partial class MyContentView : ContentView
{
MyViewModel _vm;
public MyContentView()
{
InitializeComponent();
_vm = new MyViewModel();
BindingContext = _vm;
}
protected virtual void OnAppearing()
{
_vm.Init();
}
}

这种模式在我的内容页面中运行良好,但在内容视图中不起作用。我在这里做错了什么?

内容视图没有像内容页面那样的生命周期方法。因此,当内容视图显示或显示在屏幕上时,OnAppearing((和OnDisAppearing方法开发人员自定义将不会调用。

因此,如果页面中只有一个内容视图,则可以调用页面的OnAppearing((方法来执行此操作。如果不是只有一个内容视图,则可以在使用内容视图的实例时调用_vm.Init();方法。

以下是我所做的,它似乎运行良好。

首先,我创建了一个ContentView来显示弹出型按钮标题,其中包括用户的头像和姓名。请注意,我在XAML文件中为该内容视图设置了视图模型——请参见以下内容:

<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms" 
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:xct="http://xamarin.com/schemas/2020/toolkit"
xmlns:vm="clr-namespace:MyApp.ViewModels"
x:Class="MyApp.Views.FlyoutHeader">
<ContentView.BindingContext>
<vm:AppViewModel/>
</ContentView.BindingContext>
<ContentView.Content>
<StackLayout
BackgroundColor="{StaticResource PrimaryDark }"
HeightRequest="200">
<xct:AvatarView
Source="{Binding UserInfo.AvatarUrl}"
Size="100"
HorizontalOptions="CenterAndExpand"
VerticalOptions="CenterAndExpand"/>
<Label
Text="{Binding UserInfo.FullName}"
TextColor="White"
FontSize="Medium"
FontAttributes="Bold"
HorizontalOptions="CenterAndExpand"
Margin="0,0,0,30"/>
</StackLayout>
</ContentView.Content>
</ContentView>

然后,我创建了一个名为AppViewModel的视图模型,我打算在多个地方使用它,包括我上面共享的FlyoutHeader.xaml。以下是AppViewModel的样子:

public class AppViewModel : BaseViewModel
{
User user { get; set; }
public AppViewModel()
{
}
public User UserInfo
{
get => user;
set
{
if (user == value)
return;
user = value;
OnPropertyChanged();
}
}
public async void Init()
{
if(user == null || user.Id == Guid.Empty)
{
var data = await _dbService.GetUser();
if(data != null)
{
UserInfo = data;
OnPropertyChanged();
}
}
}
}

最后,在FlyoutHeader.xaml.cs的代码中,我在构造函数中调用视图模型的Init()方法:

public partial class FlyoutHeader : ContentView
{
AppViewModel _vm;
public FlyoutHeader()
{
InitializeComponent();
_vm = new AppViewModel();
_vm.Init();
BindingContext = _vm;
}
}

实际上,我有点担心UI可能存在紧密耦合,并且在构造函数中启动的async调用可能会占用UI线程并延迟它。请告诉我是否有更好的方法来处理此问题。

最新更新