【问题标题】:How to initialize data and make data binding work properly in xamarin.forms?如何在 xamarin.forms 中初始化数据并使数据绑定正常工作?
【发布时间】:2020-10-29 15:24:15
【问题描述】:

我从这个tutorial 中学习并尝试使用主详细信息页面构建我自己的时间跟踪器应用程序。但是我遇到了一个问题。这是该问题的类似快速演示:

对于 MasterDetailPageDetail.xaml

<?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:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             mc:Ignorable="d"
             xmlns:local="clr-namespace:QuickDemo"          
             x:Class="QuickDemo.MasterDetailPageDetail"
             Title="Detail">
    <TabbedPage.Children>
        <NavigationPage Title="Tab One">
            <x:Arguments>
                <local:FirstPage BindingContext="{Binding FirstPageModel}" />
            </x:Arguments>
        </NavigationPage>
        <NavigationPage Title="Tab Two">

        </NavigationPage>
    </TabbedPage.Children>
  
</TabbedPage>

对于 FirstPage.xaml

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             mc:Ignorable="d"
             NavigationPage.HasNavigationBar="False"
             xmlns:buttons="clr-namespace:QuickDemo.Views.Buttons"
             x:Class="QuickDemo.FirstPage">
    <ContentPage.Content>
        <StackLayout>
            <StackLayout Padding="20,20,20,5">
                <Label Text="{Binding CurrentStartDate, StringFormat='{0:h:mm tt}'}"
                       FontSize="20"
                       TextColor="Black"/>
                <Label Text="{Binding RunningTotal, StringFormat='{}{0:h\\:mm\\:ss}'}"
                       FontSize="50" HorizontalTextAlignment="Center"
                       TextColor="Black"/>
            </StackLayout>
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

对于 DetailPageModel.cs

public class DetailPageModel : PageModelBase
    {
        private FirstPageModel _firstPageModel;
        public FirstPageModel FirstPageModel
        {
            get => _firstPageModel;
            set => SetProperty(ref _firstPageModel, value);
        }

        public DetailPageModel(
            FirstPageModel firstPageModel)
        {
            FirstPageModel = firstPageModel;
        }

        public override Task InitializeAsync(object navigationData = null)
        {
            return Task.WhenAny(base.InitializeAsync(navigationData),
                FirstPageModel.InitializeAsync(null));
        }
    }

对于 FirstPageModel.cs

public class FirstPageModel : PageModelBase
    {
        private DateTime _currentStartDate;
        public DateTime CurrentStartDate
        {
            get => _currentStartDate;
            set => SetProperty(ref _currentStartDate, value);
        }

        private TimeSpan _runningTotal;
        public TimeSpan RunningTotal
        {
            get => _runningTotal;
            set => SetProperty(ref _runningTotal, value);
        }

        private Timer _timer;

        public FirstPageModel()
        {
           
            this.InitializeTimer();
        }

        private void InitializeTimer()
        {
            _timer = new Timer();
            _timer.Interval = 1000;
            _timer.Enabled = false;
            _timer.Elapsed += TimerElapsed;
        }

        private void TimerElapsed(object sender, ElapsedEventArgs e)
        {
            RunningTotal += TimeSpan.FromSeconds(1);
        }

        public override async Task InitializeAsync(object navigationData)
        {
            CurrentStartDate = DateTime.Now;
            RunningTotal = new TimeSpan();
            await base.InitializeAsync(navigationData);
        }
    }

并且我在PageModelLocator.cs中注册了页面和页面模型:

public class PageModelLocator
    {
        static TinyIoCContainer _container;
        static Dictionary<Type, Type> _lookupTable;

        static PageModelLocator()
        {
            _container = new TinyIoCContainer();
            _lookupTable = new Dictionary<Type, Type>();

            // Register pages and page models
            Register<DetailPageModel, MasterDetailPageDetail>();
            Register<FirstPageModel, FirstPage>();


            // Register services (services are registered as singletons default)

        }

        public static T Resolve<T>() where T : class
        {
            return _container.Resolve<T>();
        }

        public static Page CreatePageFor(Type pageModelType)
        {
            var pageType = _lookupTable[pageModelType];
            var page = (Page)Activator.CreateInstance(pageType);
            var pageModel = _container.Resolve(pageModelType);
            page.BindingContext = pageModel;
            return page;
        }

        static void Register<TPageModel, TPage>() where TPageModel : PageModelBase where TPage : Page
        {
            _lookupTable.Add(typeof(TPageModel), typeof(TPage));
            _container.Register<TPageModel>();
        }
    }

PageModelBase.cs 和 ExtendedBindableObject.cs 与教程相同。当我运行模拟器时,我得到了这个结果:

我认为会有一个 DateTime 字符串和一个零时间跨度。我觉得 FirstPageModel 中的数据根本没有初始化。我还尝试在构造函数中设置 CurrentStartTime。得到了同样的结果。

我是否错过了在 FirstPage 上显示 CurrentStartDate 和 RunningTotal 的内容?任何帮助或提示将不胜感激。提前致谢。

【问题讨论】:

    标签: xamarin xamarin.forms data-binding xamarin.android xamarin.ios


    【解决方案1】:

    我相信您的MasterDetailPageDetail 没有被初始化(或者BindingContext 没有被初始化)。教程中的架构在导航事件期间设置BindingContext。由于您在 MasterDetailPage 的 XAML 中显式设置 Master 和 Detail,因此没有显式设置绑定上下文,也没有调用 InitializeAsync 方法。

    在导航服务中添加初始化

    if (setRoot) 之后和if (page is TabbedPage tabbedPage) 之前使用以下内容更新NavigationServiceNavigateToAsync 方法:

    if (page is MasterDetailPage mdp)
    {
         App.Current.MainPage = mdp;
         // We need to initialize both Master's BindingContext as
         // well as Detail's BindingContext if they are PageModelBases
         if (mdp.Master.BindingContext is PageModelBase masterPM)
         {
             await masterPM.InitializeAsync(null);
         }
         if (mdp.Detail.BindingContext is PageModelBase detailPM)
         {
             await detailPM.InitializeAsync(null);
         }
    }
    else if (page is TabbedPage tabbedPage) 
    // .... existing code here
    

    确保为页面(主页面和细节页面)设置绑定上下文。您可以在 XAML 中执行此操作,也可以像对选项卡式页面所做的那样在 MasterDetailPage 和 PageModel 中解析

    如果需要,我可以制作一个视频来介绍这一点,并将其添加到系列中。希望这会有所帮助!

    干杯, 帕特里克

    【讨论】:

    • 嗨帕特里克。我终于使它适用于详细信息页面,就像选项卡式页面一样。但是,当我单击从母版页菜单进入该详细信息页面时,它不起作用。如果您可以将其添加到系列中,那就太好了!非常感谢!
    猜你喜欢
    • 1970-01-01
    • 2021-08-19
    • 2017-09-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-25
    • 2015-09-28
    • 2020-01-25
    相关资源
    最近更新 更多