Xamarin формирует модель представления TabbedPage, вызываемую несколько раз - PullRequest
0 голосов
/ 29 февраля 2020

Я реализовал Tabbedpage, используя ViewModel, но мой конструктор ViewModel вызывает 4 раза, потому что я создаю 4 вкладки, я также использовал призму для привязки 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>

Ниже мой код

public partial class DashboardPage : TabbedPage
    {
        private DashboardPageViewModel vm;
        public DashboardPage()
        {
            try
            {
                InitializeComponent();
                vm = BindingContext as DashboardPageViewModel;

            }
            catch (Exception ex)
            {

            }

        }
}

Ниже мой 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);
                }
            }
        }
}

1 Ответ

0 голосов
/ 29 февраля 2020

Я вижу, что вы пытаетесь сделать. Вы хотите инициализировать свой экземпляр vm, чтобы иметь к нему доступ из своего представления.

Вместо этого:

vm = BindingContext as DashboardPageViewModel;

, что мы можем сделать, это изменить тип существующего BindingContext сделав это:

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

     public DashboardPage()
     {
        InitializeComponent();
     }
}

теперь вы можете просто получить доступ к BindingContext.DoSomething, потому что его тип теперь DashboardPageViewModel.

Теперь, когда все в порядке, ваша модель представления не должна вызываться 4 раз! Что-то здесь не так. Вот контрольный список действий, которые могут вызвать конструктор, вызываемый 4 раза, так как было предоставлено немного больше информации.

  • Попробуйте удалить <NavigationPage.TitleView> сегмент.
  • Make убедитесь, что вы переходите на DashboardPage.
  • Убедитесь, что у каждого отдельного TabbedPage есть своя собственная модель просмотра.
  • Попробуйте удалить prism:ViewModelLocator.AutowireViewModel="True" и вручную добавить модель представления в TabbedPage.

Наконец, конструкторы должны быть в состоянии работать очень быстро и должны только использоваться для присваивания переменных или создания экземпляров или очень быстрых операций. То, что вы могли бы сделать, это отделить код в вашей виртуальной машине:

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();
 }

Надеюсь, это действительно поможет вам.

Примечание: Весь этот код был написан на лету и никогда не компилировался, могут быть некоторые ошибки.

...