【问题标题】:Calling one of child pages of TabbedPage to reach entry text调用 TabbedPage 的子页面之一以到达条目文本
【发布时间】:2020-05-07 03:08:10
【问题描述】:

我知道,“强烈建议使用 MVVM”,但我只是想了解和学习 xamarin.forms 结构。所以这是一个问题: 我的应用程序基于 TabbedPage,它由两个 NavigationPage 组成:

<TabbedPage.Children >
    <NavigationPage Title="Search">
        <NavigationPage.Icon>
            <OnPlatform x:TypeArguments="FileImageSource">
                <On Platform="iOS" Value="tab_feed.png"/>
            </OnPlatform>
        </NavigationPage.Icon>
        <x:Arguments>
            <views:SearchPage />                
        </x:Arguments>
    </NavigationPage>

    <NavigationPage Title="Study">
        <NavigationPage.Icon>
            <OnPlatform x:TypeArguments="FileImageSource">
                <On Platform="iOS" Value="tab_about.png"/>
            </OnPlatform>
        </NavigationPage.Icon>
        <x:Arguments> <!---->
            <views:AboutPage />
        </x:Arguments>
    </NavigationPage>
</TabbedPage.Children>

我正在尝试从在不同的类/视图模型中创建的方法调用此标签页的子页面以访问 SearchBar 文本:

    public async void AddToList()
    {
        var mp = (MainPage)App.Current.MainPage;
        var sp = (SearchPage)mp.Children[0]; /// exception related with casting is thrown.
        var Word = sp.WordSearchBar.Text;
        ...
    }

SearchPage 定义如下。所以我创建铸造异常的问题是什么。以及如何访问 searcbar 文本(绑定和 MVVM 除外)

public partial class SearchPage : ContentPage
{....}

【问题讨论】:

    标签: c# xamarin.forms casting tabbedpage


    【解决方案1】:

    mp.Children[0]; 有点像 NavigationPage 而不是 SearchPage,所以你会得到强制转换异常。

    实现此目的的一种方法是在 App 类中创建一个静态属性:

    public partial class `App` : Application
    {
        public static AboutPage aboutPageInstance { get; set; }
    
        public App()
        {
            InitializeComponent();
    
            DependencyService.Register<MockDataStore>();
            MainPage = new MainPage();
        }
    }
    

    然后在AboutPage 中分配值,假设您在AboutPage 中有一个名为currentLabel 的标签:

    public partial class AboutPage : ContentPage
    {
        public Label currentLabel { get; set; }
    
        public AboutPage()
        {
            InitializeComponent();
    
            currentLabel = myLabel;
            App.aboutPageInstance = this;
        }
    }
    

    然后您可以通过以下方式访问其他 ContentPage 中的标签:

    async void AddToList(object sender, EventArgs e)
    {
    
        if (App.aboutPageInstance != null)
        {
            AboutPage about = App.aboutPageInstance;
    
            about.currentLabel.Text = "kkk";
        }
    }
    

    MessagingCenter 也是在两个不同的 ContentPage 之间进行通信的不错选择。

    【讨论】:

    • 谢谢。这是一个很好的捷径。顺便说一句,正如您所见,“SearchPage”是 NavigationPage 的一个参数。首先,我认为应该有一种方法可以从 Children[0] 调用它。但我不能,它是 NavigationPage 的工作方式吗?
    • NavigationPage 没有名为 Children 的属性。它只有 currentPage 和 rootPage。
    • 实际上,我的意思是 MainPage.Children[0] 并希望到达 NavigationPage 并且这有效。我想,如果 SearchPage 通过 X:attribute 附加到 NavigationPage,我们应该能够通过属性访问它。显然没有办法做到这一点。后来我了解到 x:attribute 用于建筑目的,它不是属性。感谢支持。
    【解决方案2】:

    在AddToList 方法中,您尝试将MainPage 的第一个孩子强制转换为SearchPage。无论如何,在您的 XAML 中,&lt;TabbedPage.Children&gt; 中的第一个孩子是NavigationPage,它当然不是从您的SearchPage 派生的,因此无法强制转换并抛出InvalidCastException。

    如果你真的想这样做(立即学习 MVVM 可能会有所帮助,但如果你真的想通过艰苦的方式学习它,这对我来说很好),你将不得不访问NavigationPage,然后访问其CurrentPage

    public async void AddToList()
    {
        var mainPage = (MainPage)App.Current.MainPage;
        var navigationPage = (NavigationPage)mainPage.Children[0];
    
        if (navigationPage.CurrentPage is SearchPage searchPage)
        {
            var Word = searchPage.WordSearchBar.Text;
            ...
        }
    }
    

    我引入了带有模式匹配的安全转换,因为NavigationPage.CurrentPage 可能会发生变化(与MainPage 和NavigationPage 不同),我们不希望我们的应用程序因为错误的页面而崩溃在导航页面中处于活动状态。

    请注意,这样一来,您的页面就会非常紧密地耦合在一起,这通常被认为不是一件好事。即使没有 MVVM,您也应该考虑将页面解耦,例如使用 MessagingCenter,请参阅 Xamarin.Forms tutorial on loosely coupled components。无论如何,在这种情况下,您应该考虑为您的页面引入接口,因为MessagingCenter 需要发送者的类型,这会再次引入某种紧密耦合。将搜索文本发送到另一个组件可以通过调用来实现

    MessagingCenter.Send<ISearchPage, string>(this, MessengerKeys.SearchTextChanged, searchText);
    

    但究竟什么才是明智的,很大程度上取决于您的应用,并且可能有更好的方法。

    【讨论】:

    • 谢谢。这很有帮助。关于 MVVM,你是对的,我只是在尝试学习。实际上,AddToList 是通过将命令属性绑定到 MVVM 来实现的。现在我将尝试将 WordSearchBar 的文本也绑定到 MVVM 字段,看看会发生什么。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-15
    • 2021-02-09
    相关资源
    最近更新 更多