第二十三章:触发器和行为(五)

简介: 数据触发器到目前为止,您只看到在特定对象的上下文中运行的触发器。 触发器通过更改同一对象的另一个属性或通过调用影响该对象的Action来响应对象属性的更改。 EventTrigger同样响应一个对象触发的事件,以在同一个对象上调用Action。

数据触发器
到目前为止,您只看到在特定对象的上下文中运行的触发器。 触发器通过更改同一对象的另一个属性或通过调用影响该对象的Action来响应对象属性的更改。 EventTrigger同样响应一个对象触发的事件,以在同一个对象上调用Action。
DataTrigger是不同的。 与其他TriggerBase派生类似,DataTrigger附加到可视元素或在样式中定义。 但是,DataTrigger可以通过数据绑定检测另一个对象的属性更改,并更改其附加到的对象中的属性,或者(通过使用从TriggerBase继承的EnterActions和ExitActions集合)调用该对象上的TriggerAction。
DataTrigger定义以下三个属性。

  • Binding 类型是 BindingBase。
  • Object类型的Value。
  • IList类型的setter。 这是DataTrigger的content属性。

从应用程序的角度来看,DataTrigger与Trigger非常相似,只是Trigger名为Property的属性被Binding属性替换。 Trigger和DataTrigger都需要设置TargetType属性。
DataTrigger的Binding属性引用的另一个对象是什么?它可以是MVVM场景中的ViewModel或页面上的其他元素的一部分。
您可能还记得第19章“集合视图”中的SchoolOfFineArt库。该库中的Student类定义了一个名为Sex of type string的属性,该属性设置为“Male”或“Female”。下面介绍的GenderColors程序将该属性与DataTrigger结合使用,为学生设置蓝色或粉红色(无论这种颜色方案看起来多么过时。)
ListView显示高中的所有学生,ViewCell格式化每个学生以显示学生的照片,全名和当前的成绩点平均值:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:school="clr-namespace:SchoolOfFineArt;assembly=SchoolOfFineArt"
             x:Class="GenderColors.GenderColorsPage">
    <ContentPage.Padding>
        <OnPlatform x:TypeArguments="Thickness"
                    iOS="0, 20, 0, 0" />
    </ContentPage.Padding>
 
    <ContentPage.BindingContext>
        <school:SchoolViewModel />
    </ContentPage.BindingContext>
 
    <StackLayout BindingContext="{Binding StudentBody}">
        <Label Text="{Binding School}"
               FontSize="Large"
               FontAttributes="Bold"
               HorizontalTextAlignment="Center" />
        <ListView ItemsSource="{Binding Students}"
                  VerticalOptions="FillAndExpand">
            <ListView.RowHeight>
                <OnPlatform x:TypeArguments="x:Int32"
                            iOS="70"
                            Android="70"
                            WinPhone="100" />
            </ListView.RowHeight>
 
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <Grid Padding="0, 5">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="80" />
                                <ColumnDefinition Width="*" />
                            </Grid.ColumnDefinitions>
                            <Image Grid.Column="0"
                                   Source="{Binding PhotoFilename}"
                                   VerticalOptions="Center" />
                            <StackLayout Grid.Column="1"
                                         VerticalOptions="Center">
                                <Label Text="{Binding FullName}"
                                       FontSize="22"
                                       TextColor="Pink">
                                    <Label.Triggers>
                                        <DataTrigger TargetType="Label"
                                                     Binding="{Binding Sex}"
                                                     Value="Male">
                                            <Setter Property="TextColor" Value="#8080FF" />
                                        </DataTrigger>
                                    </Label.Triggers>
                                </Label>
                                <Label Text="{Binding GradePointAverage,
                                                      StringFormat='G.P.A. = {0:F2}'}"
                                       FontSize="16" />
                            </StackLayout>
                        </Grid>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </StackLayout>
</ContentPage>

该程序使用ViewCell而不是ImageCell,因此它可以访问Label,它可以附加DataTrigger。 触发器不能直接附加到Cell或Cell派生,因为没有为这些类定义触发器集合。
Label显示Student对象的FullName属性,TextColor设置为Pink。 但DataTrigger会检查Student对象的Sex属性是否等于“Male”,如果是,则使用Setter将TextColor设置为浅蓝色。 这是从单元格的其余部分隔离的Label:

<Label Text="{Binding FullName}"
       FontSize="Large"
       TextColor="Pink">
    <Label.Triggers>
        <DataTrigger TargetType="Label"
                     Binding="{Binding Sex}"
                     Value="Male">
            <Setter Property="TextColor" Value="#8080FF" />
        </DataTrigger>
    </Label.Triggers>
</Label>

DataTrigger的BindingContext与它所附加的Label的BindingContext相同。 BindingContext是一个特定的Student对象,因此DataTrigger上的Binding只需要指定Sex属性。
这是在运行结果:
2019_04_03_210916
直接从Student对象的Sex属性到Label(或ImageCell)的TextColor属性的数据绑定可以完全相似,但它需要一个绑定转换器。 DataTrigger无需任何其他代码即可完成工作。
但是,DataTrigger本身无法模仿第19章中的ColorCodedStudents程序。如果该学生的成绩点平均值危险地低于2.0标准,则该程序将显示红色的学生。小于数字的比较需要一些代码。这也是一个行为的工作,一旦你在本章后面了解了行为,你应该能够自己编写这样的代码。
DataTrigger也可以引用页面上的另一个元素来监视该元素的属性。
例如,图形环境中的一个经典任务是,如果没有在文本输入字段中输入任何内容,则禁用按钮。也许文本输入字段是文件名,按钮执行一些代码来加载或保存该文件。如果文件名为空,则启用该按钮没有任何意义。
您可以使用DataTrigger完全在XAML中完成这项工作。这是ButtonEnabler项目中的标记:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="ButtonEnabler.ButtonEnablerPage"
             Padding="20, 50">
    <StackLayout Spacing="20">
        <Entry x:Name="entry"
               Text=""
               Keyboard="Url"
               Placeholder="enter filename" />
        <Button Text="Save"
                FontSize="Large"
                HorizontalOptions="Center">
            <Button.Triggers>
                <DataTrigger TargetType="Button"
                             Binding="{Binding Source={x:Reference entry},
                                               Path=Text.Length}"
                             Value="0">
                    <Setter Property="IsEnabled" Value="False" />
                </DataTrigger>
            </Button.Triggers>
        </Button>
    </StackLayout>
</ContentPage>

Button上的DataTrigger使用引用Entry元素的Source设置其Binding属性。 Path设置为Text.Length。 Entry元素的Text属性是string类型,Length是string的属性,因此this binding指的是Entry元素中输入的字符数。 DataTrigger的Value属性设置为零,因此当Entry中输入零个字符时,将调用Setter属性,该属性将Button的IsEnabled属性设置为False。
根据Entry元素中的输入,此处显示的iPhone和Windows 10 Mobile屏幕上的按钮被禁用,但在Android屏幕上启用:
2019_04_03_211411
虽然这代表了对用户界面的微小增强,但如果您没有DataTrigger,则需要在Entry的TextChanged处理程序中的代码中实现此增强功能,或者您需要为绑定编写绑定转换器 Button的IsEnabled属性和Entry的Text.Length属性之间。
ButtonEnabler中的XAML文件包含一个您可能没有注意到的关键属性设置:

<Entry __ Text="" __ />

首次创建Entry时,Text属性不是空字符串而是null,这意味着DataTrigger中的数据绑定正在尝试引用空字符串对象的Length属性,并且它将失败。 由于绑定失败,因此在程序首次启动时将启用Button。 只有在用户键入字符和退格后,它才会被禁用。
将Text属性初始化为空字符串没有其他效果,但允许DataTrigger在程序启动时工作。

目录
相关文章
|
JavaScript Android开发
第二十三章:触发器和行为(十二)
淡化和定向在本书中,您已经看到了几个颜色选择程序,可以通过使用三个Slider元素以交互方式形成颜色。 本章的最后一个示例是另一个颜色选择程序,但是这个程序为您提供了选项:它包含三个标记为“RGB Hex”,“RGB Float”和“HSL”的单选按钮(实际上是简单的Label元素)。
678 0
|
JavaScript Android开发
第二十三章:触发器和行为(十一)
单选按钮内置于旧汽车仪表板中的无线电通常具有一排六个(左右)按钮,可以为各种无线电台“编程”。 按下其中一个按钮会导致无线电跳转到该预选电台,并且还会弹出前一个选择按钮。那些旧的汽车收音机现在是古董,但我们的电脑屏幕上的互斥选项仍然由我们称为单选按钮的视觉对象表示。
883 0
|
JavaScript Android开发
第二十三章:触发器和行为(十)
响应水龙头切换视图的各种表现形式演示了一种响应XAML文件中的点击的方法。 如果将tap事件集成到VisualElement类中,您可以使用EventTrigger更直接且更轻松地获取它们。 但是您无法将EventTrigger附加到TapGestureRecognizer。
523 0
|
JavaScript Android开发 Windows
第二十三章:触发器和行为(九)
切换和复选框在第15章“交互式界面”和第16章“数据绑定”中,您了解了如何构造传统的CheckBox视图。 但是,自定义视图的另一种方法是将视图的交互逻辑合并到行为中,然后完全在XAML中实现视觉效果。
704 0
|
Android开发
第二十三章:触发器和行为(八)
具有属性的行为Behavior 类派生自Behavior类,该类派生自BindableObject。这表明您的Behavior 派生可以定义自己的可绑定属性。之前你看过一些Action 衍生产品,比如ScaleAction和ShiverAction,它们定义了一些属性以赋予它们更大的灵活性。
622 0
|
JavaScript Android开发
第二十三章:触发器和行为(七)
行为 触发器和行为通常是串联讨论的,因为它们具有一些应用重叠。 有时候你会感到困惑是否使用触发器或行为,因为似乎要么这样做工作。你可以用触发器做任何事情,你也可以做一个行为。 但是,行为总是涉及一些代码,这是一个派生自Behavior 的类。
918 0
|
JavaScript Android开发
第二十三章:触发器和行为(六)
MultiTrigger中的组合条件Trigger和DataTrigger都有效地监视属性以确定它是否等于特定值。 这称为触发器的条件,如果条件为真,则调用Setter对象的集合。作为程序员,您可能会开始怀疑是否可以在触发器中具有多个条件。
623 0
|
JavaScript Android开发 Windows
第二十三章:触发器和行为(四)
更多事件触发器前一章关于动画的章节展示了一个按钮,它在点击时旋转或缩放。 虽然大多数动画示例都是为了制作有趣的演示而采取极端措施,但是按钮用一点动画来响应点击并不是不合理的。 这是EventTrigger的完美工作。
732 0
|
JavaScript Android开发
第二十三章:触发器和行为(三)
触发动作和动画虽然某些触发器可以完全在XAML中实现,但其他触发器需要一些代码支持。 如您所知,Xamarin.Forms没有直接支持在XAML中实现动画,因此如果您想使用触发器为元素设置动画,则需要一些代码。
932 0
|
JavaScript Android开发
第二十三章:触发器和行为(二)
触发器 在最普遍(和最模糊)的意义上,触发器是导致响应的条件。 更具体地说,触发器通过设置另一个属性或运行一些代码来响应属性更改或触发事件。 几乎总是,设置的属性或运行的代码涉及用户界面,并在XAML中表示。
913 0