Xamarin ListView选择项目外观

时间:2017-05-07 14:33:10

标签: c# android xamarin xamarin.forms xamarin.forms.listview

我使用MasterDetailPage创建侧边菜单,菜单项列表使用ListView实现。我想为所选项目制作自定义外观:

  • 背景颜色
  • 标签的文字颜色
  • ImageSource for icon

我该怎么做?

1 个答案:

答案 0 :(得分:0)

我在列表视图项中创建了字段IsActive,并使用绑定到此字段的DataTrigger并将所有属性设置为我需要的内容。

在XAML中

我将所选项目的颜色设置为StackLayout,因此我只隐藏ListView的原始选定颜色(在我的情况下为Android的橙色)

<ListView.ItemTemplate>

                <DataTemplate>
                    <ViewCell>
                        <StackLayout Orientation="Horizontal"
                                     Padding="16, 0, 16, 0"
                                     HeightRequest="48">

                            <StackLayout.Triggers>
                                <DataTrigger TargetType="StackLayout"
                                                 Binding="{Binding IsActive}"
                                                 Value="True">
                                    <Setter Property="BackgroundColor" Value="{StaticResource menu-background-active}"/>
                                </DataTrigger>
                            </StackLayout.Triggers>

                            <Image Source="{Binding IconSource}"
                                   VerticalOptions="Center"
                                   WidthRequest="20"/>
                            <Label Text="{Binding Title}" TextColor="Black"
                                   VerticalOptions="Center"
                                   Margin="36,0,0,0">
                                <Label.Triggers>
                                    <DataTrigger TargetType="Label"
                                                 Binding="{Binding IsActive}"
                                                 Value="True">
                                        <Setter Property="TextColor" Value="{StaticResource menu-text-active}"/>
                                    </DataTrigger>
                                </Label.Triggers>
                            </Label>
                        </StackLayout>
                    </ViewCell>
                </DataTemplate>

   </ListView.ItemTemplate>

ItemsSource项目

请注意,此类应实现INotifyPropertyChanged

public class MasterPageItem : INotifyPropertyChanged
{
    private string _title;
    private string _iconSource;
    private bool _isActive;


    public string Title
    {
        get { return _title; }
        set
        {
            _title = value;
            OnPropertyChanged(nameof(Title));
        }
    }

    /// <summary>
    /// Set or return icon file
    /// If IsActive == true
    /// will add suffix "_active" to return value,
    /// 
    /// Note:
    /// Icons file should be the pair"
    ///  - icon_name.png
    ///  - icon_name_active.png
    /// 
    /// </summary>
    public string IconSource
    {
        get
        {
            if (!IsActive)
                return _iconSource;

            return Path.GetFileNameWithoutExtension(_iconSource) + "_active" + Path.GetExtension(_iconSource);
        }
        set
        {
            _iconSource = value;
            OnPropertyChanged(nameof(IconSource));
        }
    }

    /// <summary>
    /// Is menu item is selected
    /// </summary>
    public bool IsActive
    {
        get { return _isActive; }
        set
        {
            _isActive = value;
            OnPropertyChanged());
        }
    }

    public Type TargetType { get; set; }

    // Important for data-binding

    public event PropertyChangedEventHandler PropertyChanged;
    public void OnPropertyChanged(string prop = "")
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(prop));
    }
}

然后在后面的母版页代码中我使用ItemSelected事件 更改IsActive属性

private void ListView_ItemSelected(object sender, SelectedItemChangedEventArgs e)
    {
        var item = e.SelectedItem as MasterPageItem;
        var items = listView.ItemsSource as IList<MasterPageItem>;

        //Select current item and deselect others
        for(int i = 0; i<items.Count; i++)
            items[i].IsActive = items[i] == item;

        if (item != null)
        {
            ItemSelected?.Invoke(this, item.TargetType);
            _activePage = item.TargetType;
        }
    }