C# Xamarin表单列表视图:编程选择和自定义呈现程序的问题

C# Xamarin表单列表视图:编程选择和自定义呈现程序的问题,c#,xamarin.forms,xamarin.forms.listview,C#,Xamarin.forms,Xamarin.forms.listview,我在XF listview和自定义渲染器方面遇到问题。 我需要: 更改所选项目的背景色 以编程方式在启动时预选项目 我已经能够改变所选项目的背景颜色,一切正常,除非我预先选择一个项目 对于自定义控件和渲染器,我使用了许多示例中的“标准”代码: 自定义控件: public class RRViewCell : ViewCell { public static readonly BindableProperty SelectedItemBackgroundColorPropert

我在XF listview和自定义渲染器方面遇到问题。 我需要:

  • 更改所选项目的背景色
  • 以编程方式在启动时预选项目
我已经能够改变所选项目的背景颜色,一切正常,除非我预先选择一个项目

对于自定义控件和渲染器,我使用了许多示例中的“标准”代码:

自定义控件:

    public class RRViewCell : ViewCell
{
    public static readonly BindableProperty SelectedItemBackgroundColorProperty = BindableProperty.Create("SelectedItemBackgroundColor", typeof(Color), typeof(RRViewCell), Color.Default);

    public Color SelectedItemBackgroundColor
    {
        get { return (Color)GetValue(SelectedItemBackgroundColorProperty); }
        set { SetValue(SelectedItemBackgroundColorProperty, value); }
    }
}
public class RRViewCellRendererAndroid : ViewCellRenderer
{

    private Android.Views.View _cellCore;
    private Drawable _unselectedBackground;
    private bool _selected;

    protected override Android.Views.View GetCellCore(Cell item, Android.Views.View convertView, ViewGroup parent, Context context)
    {
        _cellCore = base.GetCellCore(item, convertView, parent, context);

        _selected = false;
        _unselectedBackground = _cellCore.Background;

        return _cellCore;
    }

    protected override void OnCellPropertyChanged(object sender, PropertyChangedEventArgs args)
    {
        base.OnCellPropertyChanged(sender, args);

        if (args.PropertyName == "IsSelected")
        {
            _selected = !_selected;

            if (_selected)
            {
                var extendedViewCell = sender as RRViewCell;
                _cellCore.SetBackgroundColor(extendedViewCell.SelectedItemBackgroundColor.ToAndroid());
            }
            else
            {
                _cellCore.SetBackground(_unselectedBackground);
            }
        }
    }
}
<ctrl:RRViewCell SelectedItemBackgroundColor="{StaticResource NavigationPrimary}">
Android渲染器:

    public class RRViewCell : ViewCell
{
    public static readonly BindableProperty SelectedItemBackgroundColorProperty = BindableProperty.Create("SelectedItemBackgroundColor", typeof(Color), typeof(RRViewCell), Color.Default);

    public Color SelectedItemBackgroundColor
    {
        get { return (Color)GetValue(SelectedItemBackgroundColorProperty); }
        set { SetValue(SelectedItemBackgroundColorProperty, value); }
    }
}
public class RRViewCellRendererAndroid : ViewCellRenderer
{

    private Android.Views.View _cellCore;
    private Drawable _unselectedBackground;
    private bool _selected;

    protected override Android.Views.View GetCellCore(Cell item, Android.Views.View convertView, ViewGroup parent, Context context)
    {
        _cellCore = base.GetCellCore(item, convertView, parent, context);

        _selected = false;
        _unselectedBackground = _cellCore.Background;

        return _cellCore;
    }

    protected override void OnCellPropertyChanged(object sender, PropertyChangedEventArgs args)
    {
        base.OnCellPropertyChanged(sender, args);

        if (args.PropertyName == "IsSelected")
        {
            _selected = !_selected;

            if (_selected)
            {
                var extendedViewCell = sender as RRViewCell;
                _cellCore.SetBackgroundColor(extendedViewCell.SelectedItemBackgroundColor.ToAndroid());
            }
            else
            {
                _cellCore.SetBackground(_unselectedBackground);
            }
        }
    }
}
<ctrl:RRViewCell SelectedItemBackgroundColor="{StaticResource NavigationPrimary}">
XAML:

    public class RRViewCell : ViewCell
{
    public static readonly BindableProperty SelectedItemBackgroundColorProperty = BindableProperty.Create("SelectedItemBackgroundColor", typeof(Color), typeof(RRViewCell), Color.Default);

    public Color SelectedItemBackgroundColor
    {
        get { return (Color)GetValue(SelectedItemBackgroundColorProperty); }
        set { SetValue(SelectedItemBackgroundColorProperty, value); }
    }
}
public class RRViewCellRendererAndroid : ViewCellRenderer
{

    private Android.Views.View _cellCore;
    private Drawable _unselectedBackground;
    private bool _selected;

    protected override Android.Views.View GetCellCore(Cell item, Android.Views.View convertView, ViewGroup parent, Context context)
    {
        _cellCore = base.GetCellCore(item, convertView, parent, context);

        _selected = false;
        _unselectedBackground = _cellCore.Background;

        return _cellCore;
    }

    protected override void OnCellPropertyChanged(object sender, PropertyChangedEventArgs args)
    {
        base.OnCellPropertyChanged(sender, args);

        if (args.PropertyName == "IsSelected")
        {
            _selected = !_selected;

            if (_selected)
            {
                var extendedViewCell = sender as RRViewCell;
                _cellCore.SetBackgroundColor(extendedViewCell.SelectedItemBackgroundColor.ToAndroid());
            }
            else
            {
                _cellCore.SetBackground(_unselectedBackground);
            }
        }
    }
}
<ctrl:RRViewCell SelectedItemBackgroundColor="{StaticResource NavigationPrimary}">
结果是:

(敏感数据被屏蔽!)

在这种情况下,使用defaut背景色而不是自定义背景色

此外,如果我点击另一项,则会发生以下情况:

请注意:

  • 如果我重复点击不同的项目(第一个项目除外):
    • 第一项仍然是蓝色的
    • 最后一个点击的项目设置为蓝色,前一个项目设置为白色,所以我总是有第一个项目和最后一个点击的项目在蓝色
  • 如果我轻触第一个项目,它将变为橙色,并在随后的轻触中保持橙色
  • 在我点击第一个项目后点击另一个项目将第一个项目从橙色变成蓝色

这可能非常令人沮丧,但是有很多Xamarin的东西,这是一个横向思考的例子,但是有很多方法可以实现这一点

我通过禁用内置选择过程中的ListView实现了类似的功能,取而代之的是始终以编程方式选择所选项目,并且没有一项是特定于平台的。通过这样做,如果我正在运行一个很长的过程,例如更新列表,我还可以防止用户选择产生影响

我将
ListView.SelectionMode
设置为None,而让
ListView.ItemTapped
触发我的选择代码。 “我的ListView”的每个源项都有一个IsSelected属性,该属性在选择项进行查看时设置。 我没有改变ListView.Item的背景色,而是使用一个固定背景色的BoxView,它的IsVisible绑定到IsSelected,例如

        <ListView.ItemTemplate>
            <DataTemplate>
                <ViewCell>
                    <Grid  RowSpacing="0" >
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="1"/>
                            <ColumnDefinition Width="60"/>
                            <ColumnDefinition Width="120"/>
                            <ColumnDefinition Width="100*"/>
                            <ColumnDefinition Width="40"/>
                            <ColumnDefinition Width="1" />
                        </Grid.ColumnDefinitions>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="30*"/>
                        </Grid.RowDefinitions>
                        <BoxView Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="6" BackgroundColor="{StaticResource Primary}" IsVisible="{Binding IsSelected}" />
                        <Label   Grid.Column="1" Grid.Row="0" HorizontalTextAlignment="Center" VerticalOptions="Center" Text="{Binding Destination}"/>
                        <Label   Grid.Column="2" Grid.Row="0" HorizontalTextAlignment="Start" VerticalOptions="Center" Text="{Binding Description}"/>
                        <Label   Grid.Column="3" Grid.Row="0" HorizontalTextAlignment="End"  HorizontalOptions="End" VerticalOptions="Center" Text="{Binding ScaledValue}" FontAttributes="Bold" FontSize="Medium" BackgroundColor="{Binding StoredValueDiffers, Converter={x:StaticResource StoredDiffersConverter}}"/>
                        <Label   Grid.Column="4" Grid.Row="0" HorizontalTextAlignment="Start" VerticalOptions="Center" Text="{Binding Units}"/>
                    </Grid>
                </ViewCell>
            </DataTemplate>
        </ListView.ItemTemplate>

因为BoxView是首先声明的,所以它位于最底层,而其他组件则在其上绘制

我想在你的例子中,你可以使用一个非布尔值来显示一个项目是否被手动选择(点击),是否被编程选择,然后转换器会选择你的背景颜色


我希望这能给你一些想法。

在Android中,最简单的方法是在
Resources\values
下编辑:

styles.xml中添加此行:

<style name="MainTheme.Base" parent="Theme.AppCompat.Light.DarkActionBar">
     ...
   <item name="android:colorActivatedHighlight">@color/ListViewSelected</item>
    ...
</style>
<color name="ListViewSelected">#96BCE3</color>

缺点是,一旦设置,所有ListView都将启用此效果

它可以工作吗?