更改选定项目列表视图的背景颜色

本文关键字:视图 背景 颜色 列表 项目 | 更新日期: 2023-09-27 18:18:10

我有一个关于Xamarin中的listview的问题。形式绑定我的列表视图成功与一些项目,但我想改变选定单元格的背景颜色,我如何做到这一点在Xamarin。形式

我利用

var cell = DataTemplate(typeof(ImageCell));
ListView listView = new ListView
{
    SeparatorColor = Color.Green,
    ItemsSource = ListlvData,
    ItemTemplate = cell, // Set the ImageCell to the item templatefor the listview
};

更改选定项目列表视图的背景颜色

编辑2:

有时候,如果我遇到奇怪的问题,我的ViewCellBackgroundColor永远不会变回原来的颜色,所以我已经开始这样做来改变颜色:

cell.Tapped += async (sender, args) => {
    cell.View.BackgroundColor = Color.Red;
#pragma warning disable 4014 //These pragma's are only needed if your Tapped is being assigned an async anonymous function and muffles the compiler warning that you did not await Task.Run() which you do not want to fire and forget it
    Task.Run(async () => {     //Change the background color back after a small delay, no matter what happens
        await Task.Delay(300); //Or how ever long to wait
        Device.BeginInvokeOnMainThread(() => cell.View.BackgroundColor = Color.Default); //Turn it back to the default color after your event code is done
    });
#pragma warning restore 4014
    await OnListViewTextCellTapped(cell); //Run your actual `Tapped` event code
};
编辑:

要将以下代码添加到ListView.DataTemplate中,您需要这样做:

ListView listView = new ListView {
    SeparatorColor = Color.Green,
    ItemsSource    = ListlvData
};
listView.ItemTemplate = new DataTemplate(() => {
    ViewCell cell = new ViewCell();
    cell.Tapped += (sender, args) => {
        cell.View.BackgroundColor = Color.Red;
        OnListViewTextCellTapped(cell);            //Run your actual `Tapped` event code
        cell.View.BackgroundColor = Color.Default; //Turn it back to the default color after your event code is done
    };
    cell.View = new Image();
    return cell;
});

要更改Tapped的背景颜色,您需要在其中使用ViewCellImage控件,因为ImageCell默认不支持BackgroundColor

我把StackLayoutViewCell,但然后在Tapped事件,我改变ViewCell.ViewBackgroundColor,像这样:

ViewCell cell = new ViewCell();
cell.Tapped += (sender, args) => {
    cell.View.BackgroundColor = Color.Red;
    OnListViewTextCellTapped(cell);            //Run your actual `Tapped` event code
    cell.View.BackgroundColor = Color.Default; //Turn it back to the default color after your event code is done
};

我知道这个问题已经回答了很长一段时间了,但是我想我应该在这里为那些可能遇到这个问题的人提供更多的信息,这些人正在寻找一种更MVVM友好的方式来做到这一点。我最后写了下面这篇文章,如果有人愿意的话,希望能对他们有用。

您将需要一个如下所示的值转换器:

public class UseColorIfConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return (bool)value ? parameter : Color.Transparent;
    }
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

如果提供的参数求值为true,转换器将返回相应的Color。我还将此转换器注册为我的App.xaml中的静态资源(必须手动创建),即:

<?xml version="1.0" encoding="utf-8" ?>
<forms:FormsApplication xmlns="http://xamarin.com/schemas/2014/forms"
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         xmlns:forms="clr-namespace:Caliburn.Micro.Xamarin.Forms;assembly=Caliburn.Micro.Platform.Xamarin.Forms"
         x:Class="Path.To.Application.App"
         xmlns:converters="clr-namespace:Path.To.Converters.Namespace;assembly=Converter.Assembly">
    <Application.Resources>
         <converters:UseColorIfConverter x:Key="UseColorIf"></converters:UseColorIfConverter>
    </Application.Resources>
</forms:FormsApplication>

请注意,我使用的是Caliburn Micro,但是同样的情况也适用于默认的Xamarin.Forms.Application类。

转换器和潜在绑定的用法如下:

<ListView ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem}">
    <ListView.ItemTemplate>
        <DataTemplate>
            <ViewCell>
                <ContentView BackgroundColor="{Binding Path=Selected, Converter={StaticResource UseColorIf}, ConverterParameter={x:StaticResource ListSelectionColor}}" ...>
                    <!--Display-->
                </ContentView>
            </ViewCell>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

这允许您绑定每个视图模型中的属性,该属性指示它是否被选中。此属性必须保持同步,但很容易通过订阅属性更改事件来完成,例如:

public class MenuViewModel : Screen
{
    public BindableCollection<SectionViewModel> Items { get; }    
    public MenuViewModel(IEnumerable<SectionViewModel> sections)
    {
        Items = new BindableCollection<SectionViewModel>(sections);
        PropertyChanged += OnPropertyChanged;
    }
    private SectionViewModel _selectedItem;
    public SectionViewModel SelectedItem
    {
        get { return _selectedItem; }
        set
        {
            if (_selectedItem == value)
                return;
            _selectedItem = value;
            NotifyOfPropertyChange(nameof(SelectedItem));
        }
    }
    private void OnPropertyChanged(object sender, PropertyChangedEventArgs propertyChangedEventArgs)
    {
        if (propertyChangedEventArgs.PropertyName == nameof(SelectedItem))
        {
            foreach (var item in Items)
            {
                item.Selected = item == SelectedItem;
            }
        }
    }
}

这样做之后还有一个小问题,那就是每个平台上使用的默认渲染器。我没有检查Android,但至少在IOS上,你仍然会得到一个灰色的边框,所以下面只是删除它:

using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ExportRenderer(typeof(ViewCell), typeof(CustomListViewCellRenderer))]
namespace My.Awesome.Ios.Client.Renderers
{
    class CustomListViewCellRenderer : ViewCellRenderer
    {
        public override UITableViewCell GetCell(Cell item, UITableViewCell reusableCell, UITableView tv)
        {
            var cell = base.GetCell(item, reusableCell, tv);
            cell.SelectionStyle = UITableViewCellSelectionStyle.None;
            return cell;
        }
    }
}