Mvvm Xamarin表单选项卡页面视图模型称为多次

Mvvm Xamarin表单选项卡页面视图模型称为多次,mvvm,xamarin.forms,xamarin.android,tabbedpage,Mvvm,Xamarin.forms,Xamarin.android,Tabbedpage,我已经使用ViewModel实现了Tabbedpage,但是我的ViewModel构造函数调用了4次,因为我创建了4个选项卡,我还使用prism进行ViewModel绑定 下面是一个设计文件 <?xml version="1.0" encoding="UTF-8"?> <TabbedPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.

我已经使用ViewModel实现了Tabbedpage,但是我的ViewModel构造函数调用了4次,因为我创建了4个选项卡,我还使用prism进行ViewModel绑定

下面是一个设计文件

<?xml version="1.0" encoding="UTF-8"?>

<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms" 
            xmlns:material="clr-namespace:XF.Material.Forms.UI;assembly=XF.Material"
            xmlns:ffimageloading="clr-namespace:FFImageLoading.Forms;assembly=FFImageLoading.Forms"
            xmlns:ffTransformations="clr-namespace:FFImageLoading.Transformations;assembly=FFImageLoading.Transformations" 
            prism:ViewModelLocator.AutowireViewModel="True"
             xmlns:ios="clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core"
            xmlns:extended="clr-namespace:Xamarin.Forms.Extended;assembly=Xamarin.Forms.Extended.InfiniteScrolling"
            xmlns:customcontrols="clr-namespace:QuranicQuizzes.CustomControls"
            xmlns:local="clr-namespace:QuranicQuizzes.Views" NavigationPage.HasNavigationBar="True"
             x:Class="QuranicQuizzes.Views.DashboardPage">
      <NavigationPage.TitleView>
        <StackLayout Orientation="Horizontal" HorizontalOptions="FillAndExpand">
            <Label Text="Dashboard" TextColor="White" HorizontalTextAlignment="Center" HorizontalOptions="CenterAndExpand" VerticalTextAlignment="Center" FontFamily="{StaticResource QuranFontBold}" FontSize="Medium" />
            <StackLayout Orientation="Horizontal">
               <material:MaterialMenuButton x:Name="Menus" ButtonType="Text" Image="list" TintColor="White" BackgroundColor="Transparent" CornerRadius="24" Choices="{Binding Actions}"  MenuSelected="MaterialMenuButton_MenuSelected"  />
            </StackLayout>

        </StackLayout>
    </NavigationPage.TitleView>
        <local:HomeTabPage/>
        <local:QuizzesTabPage/>
        <local:LiveGameTabPage/>
        <local:AssignmentTabPage/>

</TabbedPage>
下面是我的ViewModel

public class DashboardPageViewModel : ViewModelBase
{
 INavigationService _navigationService;
        IClientAPI _clientAPI;
        Dashboards dashboard;
   public DashboardPageViewModel(INavigationService navigationService, IClientAPI clientAPI) : base(navigationService)
        {
            _navigationService = navigationService;
            _clientAPI = clientAPI;

            if (CrossConnectivity.Current.IsConnected)
            {
                var StartDate = DateTime.Now.AddDays(-7).ToString("yyyy-MM-dd");
                var Enddate = DateTime.Now.ToString("yyyy-MM-dd");
                if (dashboard == null)
                {
                    dashboard = new Dashboards();
                    getDashboardData(StartDate, Enddate);
                }
            }
        }
}

我明白你想做什么了。您希望初始化vm实例,以便可以从视图中访问vm

而不是这样做:

vm = BindingContext as DashboardPageViewModel;
public partial class DashboardPage
{
     new DashboardPageViewModel BindingContext
     {
        get => (DashboardPageViewModel) base.BindingContext;
        set => base.BindingContext = value;
     }

     public DashboardPage()
     {
        InitializeComponent();
     }
}
我们可以通过以下操作更改现有BindingContext属性的类型:

vm = BindingContext as DashboardPageViewModel;
public partial class DashboardPage
{
     new DashboardPageViewModel BindingContext
     {
        get => (DashboardPageViewModel) base.BindingContext;
        set => base.BindingContext = value;
     }

     public DashboardPage()
     {
        InitializeComponent();
     }
}
现在您可以只访问
BindingContext.DoSomething
,因为它的类型现在是
DashboardPageViewModel

现在已经解决了,您的viewmodel不应该被调用4次!这里有点不对劲。这里有一个清单,列出了一些可能会导致构造函数被调用4次的事情,因为没有提供更多的信息

  • 尝试删除
  • 确保您正在导航到仪表板页面
  • 确保每个选项卡页都有自己的viewmodel
  • 尝试删除prism:ViewModelLocator.AutowireViewModel=“True”,然后手动将viewmodel添加到选项卡页面
最后,构造函数应该能够非常快速地运行,并且应该用于分配变量、实例化或非常快速的操作。您可以做的是分离VM中的代码:

public class DashboardPageViewModel : ViewModelBase
{
    IClientAPI _clientAPI;
    Dashboards dashboard;

    public DashboardPageViewModel(INavigationService navigationService, IClientAPI clientAPI) : base(navigationService)
    {
        _clientAPI = clientAPI;
    }

    public void Init()
    {
        if (CrossConnectivity.Current.IsConnected)
        {
            var StartDate = DateTime.Now.AddDays(-7).ToString("yyyy-MM-dd");
            var Enddate = DateTime.Now.ToString("yyyy-MM-dd");
            if (dashboard == null)
            {
                dashboard = new Dashboards();
                getDashboardData(StartDate, Enddate);
            }
        }
    }        
}
然后在您看来,您可以添加以下方法:

protected override void OnBindingContextChanged()
{
    base.OnBindingContextChanged();

     if(BindingContext == null)
     {
         return;
     }

     BindingContext.Init();
 }
我希望这真的对你有帮助

NB:所有这些代码都是动态编写的,从未编译过,可能有一些错误