第十九章:集合视图(五)

数据绑定所选项目
使用所选项的一种方法涉及在代码隐藏文件中处理ListView的ItemSelected事件,并使用SelectedItem属性获取新选择的项。 (本章稍后将举例说明。)但在许多情况下,您需要使用与SelectedItem属性的数据绑定。 ListViewArray程序使用BoxView的Color属性定义ListView的SelectedItem属性之间的数据绑定:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="ListViewArray.ListViewArrayPage">
    <ContentPage.Padding>
        <OnPlatform x:TypeArguments="Thickness"
                    iOS="10, 20, 10, 0"
                    Android="10, 0"
                    WinPhone="10, 0" />
    </ContentPage.Padding>
    <StackLayout>
        <ListView x:Name="listView"
                  SelectedItem="{Binding Source={x:Reference boxView},
                                         Path=Color,
                                         Mode=TwoWay}">
            <ListView.ItemsSource>
                <x:Array Type="{x:Type Color}">
                    <x:Static Member="Color.Aqua" />
                    <x:Static Member="Color.Black" />
                    <x:Static Member="Color.Blue" />
                    <x:Static Member="Color.Fuchsia" />
                    <x:Static Member="Color.Gray" />
                    <x:Static Member="Color.Green" />
                    <x:Static Member="Color.Lime" />
                    <x:Static Member="Color.Maroon" />
                    <Color>Navy</Color>
                    <Color>Olive</Color>
                    <Color>Pink</Color>
                    <Color>Purple</Color>
                    <Color>Red</Color>
                    <Color>Silver</Color>
                    <Color>Teal</Color>
                    <Color>White</Color>
                    <Color>Yellow</Color>
                </x:Array>
            </ListView.ItemsSource>
        </ListView>
        <BoxView x:Name="boxView"
                 Color="Lime"
                 HeightRequest="100" /> 
 
    </StackLayout>
</ContentPage>

此XAML文件直接从项数组中设置ListView的ItemsSource属性。 ItemsSource不是ListView的内容属性(实际上,ListView根本没有内容属性),因此您需要显式的ListView.ItemsSource标记。 x:Array元素需要Type属性,指示数组中项目的类型。为了多样化,显示了两种指定颜色值的不同方法。您可以使用任何导致Color类型值的内容。
ListView的ItemsSource属性始终填充对象而不是可视元素。例如,如果要在ListView中显示字符串,请使用代码中的字符串对象或XAML文件中的x:String元素。不要使用Label元素填充ItemsSource集合!
ListView是可滚动的,通常当可滚动视图是StackLayout的子视图时,需要FillAndExpand的VerticalOptions设置。但是,ListView本身将其Horizo​​ntalOptions和VerticalOptions属性设置为FillAndExpand。
数据绑定从BoxView的Color属性定向ListView的SelectedItem属性。您可能更倾向于反转该绑定的源和目标属性,如下所示:

<BoxView x:Name="boxView"
               Color="{Binding Source={x:Reference listView},
                               Path=SelectedItem}"
               HeightRequest="100" />

但是,默认情况下,ListView的SelectedItem属性为null,表示未选择任何内容,并且绑定将失败并显示NullReferenceException。 要在BoxView上进行绑定,您需要在添加项目后初始化ListView的SelectedItem属性:

<ListView x:Name="listView">
    <ListView.ItemsSource>
        <x:Array Type="{x:Type Color}">
            __
        </x:Array>
    </ListView.ItemsSource>
    <ListView.SelectedItem>
        <Color>Lime</Color>
    </ListView.SelectedItem>
</ListView>

一个更好的方法 - 您将与MVVM一起使用的方法 - 是在ListView的SelectedItem属性上设置绑定。 SelectedItem的默认绑定模式是OneWayToSource,这意味着以下绑定将BoxView的颜色设置为ListView中选择的任何项目:

<ListView x:Name="listView"
          SelectedItem="{Binding Source={x:Reference boxView},
                                 Path=Color}">
    __
</ListView>

但是,如果您还想从绑定源初始化SelectedItem属性,请使用ListViewArray程序中的XAML文件中所示的TwoWay绑定:

<StackLayout>
    <ListView x:Name="listView"
              SelectedItem="{Binding Source={x:Reference boxView},
                                     Path=Color,
                                     Mode=TwoWay}">
        __
    </ListView>
    <BoxView x:Name="boxView"
             Color="Lime"
             HeightRequest="100" /> 
</StackLayout>

您将看到程序启动时选择ListView中的“Lime”条目:
第十九章:集合视图(五)
实际上,如果不检查RGB值,很难判断这是否真的是“Lime”条目。尽管Color结构定义了一组带有颜色名称的静态字段,但Color值本身无法通过名称进行标识。当数据绑定将Lime颜色值设置为ListView的SelectedItem属性时,ListView可能使用Color结构的Equals方法在其内容中找到匹配项,该方法比较两种颜色的组件。
ListView显示的改进当然是一个高优先级!
如果仔细检查ListViewArray屏幕,您会发现Color项目的显示顺序与它们在数组中的定义顺序不同。 ListViewArray程序还有另一个目的:演示ListView不会将集合的副本设置为其ItemsSource属性。相反,它直接将该集合对象用作项目的源。在里面
代码隐藏文件,在InitializeComponent调用返回后,ListViewArrayPage的构造函数执行就地数组排序以按顺序对项目进行排序:

public partial class ListViewArrayPage : ContentPage
{
    public ListViewArrayPage()
    {
        InitializeComponent();
        Array.Sort<Color>((Color[])listView.ItemsSource,
            (Color color1, Color color2) =>
            {
                if (color1.Hue == color2.Hue)
                    return Math.Sign(color1.Luminosity - color2.Luminosity);
                return Math.Sign(color1.Hue - color2.Hue);
            });
    }
}

这种排序发生在ItemsSource属性设置之后,当InitializeComponent调用解析XAML时,但在ListView实际在布局过程中显示其内容之前。
此代码表示您可以动态更改ListView使用的集合。 但是,如果希望ListView在集合更改时更改其显示,则必须以某种方式通知ListView其ItemsSource属性引用的集合中发生了更改。
让我们更详细地研究一下这个问题。