xamarin - 如何访问 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>
我创建了一些方法来处理 ActivityIndicator 状态,例如在需要时可见和不可见。
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();
}
}
}
我想要如下所示的输出。请查看图片。
ActivityIndicator 隐藏时的视图应该是这样的
问题是,我无法在后面的代码中访问“stackProgress”。因为它是ControlTemplate
。它是说
当前上下文中不存在名称“stackProgress”。
有没有其他方法可以实现相同的目标?或者
有人能告诉我我做错了什么吗?
我该如何解决?
解决方案
我建议您使用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;
}
推荐阅读
- objective-c - CGImage Masking 在 iOS 12 上停止工作
- mysql - 按左外连接表/关联的列/属性排序
- prometheus - Stacklight Prometheus 功能不起作用
- python - 当 pip install -e 成功时,为什么从 github 安装 pip 失败?
- c - 将文件读入数组并跳过换行符
- excel - 在 Windows 和 64 位 Mac 上打开 URL
- python-3.x - 使用 pandas 将结果打印到数据框中
- node.js - 将 MySQL 与 Socket.io 一起使用时,Node.js 脚本会冻结而不会崩溃
- python - TypeError: list indices must be integers or slices, not Node # Node is a class
- sql - Spark SQL 在联合时重复计算相同的子查询