首页 > 解决方案 > 如何访问 ControlTemplate 中的元素?

问题描述

我有一个要求,例如ActivityIndicator在执行 API 调用时会出现。这对所有页面都是一样的。所以我创建了 BasePage 并将活动指示器放在BasePage.xaml.

BasePage.xaml

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage
x:Class="XamarinFormDemo.Base.BasePage"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">

<ContentPage.ControlTemplate>

    <ControlTemplate x:Name="baseTemplate">

        <AbsoluteLayout
            AbsoluteLayout.LayoutBounds="1,1,1,1"
            HorizontalOptions="FillAndExpand"
            VerticalOptions="FillAndExpand">

            <ContentPresenter AbsoluteLayout.LayoutBounds="0, 0, 1, 1" AbsoluteLayout.LayoutFlags="All" />

            <StackLayout
                x:Name="stackProgress"
                AbsoluteLayout.LayoutBounds="0,0,1,1"
                AbsoluteLayout.LayoutFlags="All"
                BackgroundColor="#8C000000"
                HorizontalOptions="FillAndExpand"
                IsVisible="False"
                Orientation="Vertical"
                VerticalOptions="FillAndExpand">

                <ActivityIndicator
                    x:Name="indicatorProgress"
                    AbsoluteLayout.LayoutBounds="0,0,1,1"
                    AbsoluteLayout.LayoutFlags="All"
                    HorizontalOptions="Center"
                    IsRunning="True"
                    VerticalOptions="FillAndExpand"
                    Color="White" />
            </StackLayout>

        </AbsoluteLayout>

    </ControlTemplate>

</ContentPage.ControlTemplate>

</ContentPage>

我创建了一些方法来处理 ActivityIndi​​cator 状态,例如在需要时可见和不可见。

BasePage.xaml.cs

[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class BasePage : ContentPage
{

public BasePage()
{
    InitializeComponent();
}


/*
 * Show progress dialog 
 */
public void ShowProgress()
{

    if (!stackProgress.IsVisible)
    {
        stackProgress.IsVisible = true;
    }

}

/*
 * Hide progress dialog
 */
public void HideProgress()
{

    stackProgress.IsVisible = false;

  }

}

现在我创建了 LoginPage.xaml 并将 BasePage 添加为根 control.so 我可以访问指标。我对其他页面做了同样的事情。

登录页面.xaml

<?xml version="1.0" encoding="utf-8" ?>
<base:BasePage
x:Class="XamarinFormDemo.MainPage"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:base="clr-namespace:XamarinFormDemo.Base"
xmlns:local="clr-namespace:XamarinFormDemo.Controls"
BackgroundColor="#2b3d53"
NavigationPage.HasNavigationBar="False">

<ScrollView>

    <StackLayout
        Padding="24"
        HorizontalOptions="FillAndExpand"
        Orientation="Vertical"
        VerticalOptions="FillAndExpand">

        <Image
            Margin="0,32,0,32"
            HeightRequest="100"
            Source="ai_logo.jpg"
            VerticalOptions="Center"
            WidthRequest="100" />

        <local:CustomEntry
            x:Name="entryEmail"
            Margin="0,0,0,8"
            DrawableImage="email_hover_icon"
            FontSize="Small"
            IsSpellCheckEnabled="False"
            Keyboard="Email"
            Placeholder="Email"
            PlaceholderColor="Gray"
            Text="peter@klaven.com"
            TextColor="Black" />

        <local:CustomEntry
            x:Name="entryPassword"
            Margin="0,0,0,8"
            DrawableImage="password_hover_icon"
            FontSize="Small"
            IsPassword="True"
            IsSpellCheckEnabled="False"
            Placeholder="Password"
            PlaceholderColor="Gray"
            Text="cityslicka"
            TextColor="Black" />

        <Button
            x:Name="buttonLogin"
            Margin="0,16,0,16"
            BackgroundColor="#009999"
            Clicked="ButtonLogin_ClickedAsync"
            FontSize="Small"
            Text="Login"
            TextColor="White" />

        <Label
            FontSize="Small"
            HorizontalOptions="Center"
            Text="OR"
            TextColor="White" />

        <Button
            x:Name="buttonSignUp"
            Margin="0,16,0,16"
            BackgroundColor="#009999"
            Clicked="NavigateToSignUp"
            FontSize="Small"
            Text="SignUp"
            TextColor="White" />

    </StackLayout>

</ScrollView>
</base:BasePage>

LoginPage.xaml.cs文件中,我有用于调用登录和处理活动指示器的代码ShowProgress();HideProgress(); 这些方法属于BasePage.xaml.cs

登录页面.xaml.cs

    namespace XamarinFormDemo
    {
    public partial class MainPage : BasePage
    {
    public MainPage()
    {
        InitializeComponent();

    }


    private async Task ButtonLogin_ClickedAsync(object sender, EventArgs e)
    {

            ShowProgress();

           // API Call

            HideProgress();

    }
  }    
}

我想要如下所示的输出。请查看图片。

ActivityIndi​​cator 隐藏时的视图应该是这样的

调用API时View应该是这样的

问题是,我无法在后面的代码中访问“stackProgress”。因为它是ControlTemplate。它是说

当前上下文中不存在名称“stackProgress”。

有没有其他方法可以实现相同的目标?或者

有人能告诉我我做错了什么吗?

我该如何解决?

标签: xamarinxamarin.forms

解决方案


我建议您使用TemplateBinding

所以基本上你可以在你的控制模板中重用IsBusy属性:

<ControlTemplate x:Name="baseTemplate">
    <AbsoluteLayout ..>
        <ContentPresenter AbsoluteLayout.LayoutBounds="0, 0, 1, 1" AbsoluteLayout.LayoutFlags="All" />
        <StackLayout
            x:Name="stackProgress"
            ...
            IsVisible="{TemplateBinding IsBusy}"
            ...>

            <ActivityIndicator
                ...
                IsRunning="{TemplateBinding IsBusy}"
                IsVisible="{TemplateBinding IsBusy}"
                Color="White" />
        </StackLayout>
    </AbsoluteLayout>
</ControlTemplate>

现在您可以IsBusy使用 MVVM 绑定此属性,或者在代码隐藏中更新您的方法:

/*
 * Show progress dialog 
 */
public void ShowProgress()
{
    if (!IsBusy)
    {
        IsBusy = false;
    }
}

/*
 * Hide progress dialog
 */
public void HideProgress()
{
    IsBusy = false;
}

推荐阅读