如何访问ControlTemplate中的元素?

时间:2018-08-27 11:27:00

标签: xamarin xamarin.forms

我有一个要求,例如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添加为根控件。这样我就可以访问指标。我在其他页面上也做过同样的事情。

LoginPage.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

LoginPage.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();

    }
  }    
}

我想要如下输出。请看图片。

View should be like this when the ActivityIndicator is hidden

View should be like this when calling API

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

  

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

还有其他方法可以实现同一目标吗?或

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

我该如何解决?

2 个答案:

答案 0 :(得分:0)

请尝试以下代码:

<?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.Content>           
        <AbsoluteLayout
            x:Name="dd"               
            HorizontalOptions="FillAndExpand"
            VerticalOptions="FillAndExpand">               
            <ContentView x:Name="baseTemplate">
                <StackLayout 
                x:Name="stackProgress"
                AbsoluteLayout.LayoutBounds="0,0,1,1"
                AbsoluteLayout.LayoutFlags="All"
                BackgroundColor="#8C000000"
                HorizontalOptions="FillAndExpand"                    
                Orientation="Vertical"
                VerticalOptions="FillAndExpand">                       
                </StackLayout>
            </ContentView>
            <StackLayout Padding="12" x:Name="DisplayLoading" 
             IsVisible="False"
             AbsoluteLayout.LayoutFlags="PositionProportional"
             AbsoluteLayout.LayoutBounds="0.5,0.5,-1,-1">
            <ActivityIndicator Color="#d7813e" IsRunning="True"/>
            <Label Text="Loading..." TextColor="#d7813e" FontSize="Small"/>
        </StackLayout>                
<ContentPage.Content>

尝试使用CS代码,例如:

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

    /*
     * Show progress dialog 
     */
    public void ShowProgress()
    {    
        DisplayLoading.IsVisible = true;
    }

    /*
     * Hide progress dialog
     */
    public void HideProgress()
    {    
         DisplayLoading.IsVisible = false;    
    }
}

答案 1 :(得分:0)

我建议您使用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>

现在,您可以使用MVVM绑定此IsBusy属性,也可以在后台代码中更新方法:

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

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