调用 TabbedPage 的子页面之一以到达条目文本

Calling one of child pages of TabbedPage to reach entry text

我知道,"It is highly recommended to use 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>

我正在尝试通过在不同 class/view 模型中创建的方法调用此标签页的子项以访问 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 定义如下。所以我创建转换异常的问题是什么。以及如何访问搜索栏文本(绑定和 MVVM 除外)

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

AddToList 方法中,您试图将 MainPage 的第一个 child 转换为 SearchPage。无论如何,在你的 XAML 中,<TabbedPage.Children> 中的第一个 child 是一个 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 可能会发生变化(与 MainPageNavigationPage 不同)并且我们不希望我们的应用程序崩溃只是因为错误的页面在导航页面中处于活动状态。

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

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

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

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

一种实现方法是在 App class:

中创建静态 属性
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 之间进行通信的好选择。