我确实提出了一个我很满意并且不需要渲染器的解决方案。在我的自定义 ViewCell 中,我按照建议添加了 SelectedBackgroundColor BindableProperty。
/// <summary>
/// The SelectedBackgroundColor property.
/// </summary>
public static readonly BindableProperty SelectedBackgroundColorProperty =
BindableProperty.Create("SelectedBackgroundColor", typeof(Color), typeof(SymbolViewCell), Color.Transparent, propertyChanged:SelectionColorChanged);
public Color SelectedBackgroundColor
{
get => (Color)GetValue(SelectedBackgroundColorProperty);
set => SetValue(SelectedBackgroundColorProperty, value);
}
private static void SelectionColorChanged(BindableObject bindable, object oldvalue, object newvalue)
{
if ( !(bindable is SymbolViewCell viewCell) ) return;
var color = (Color) newvalue;
viewCell.View.BackgroundColor = color;
}
然后我使用自定义转换器。这实际上是一个通用转换器,用于在其他地方根据真/假界限值设置值。
public class ConfigurableBoolConverter<T> : IValueConverter
{
public ConfigurableBoolConverter() { }
public ConfigurableBoolConverter(T trueResult, T falseResult)
{
TrueResult = trueResult;
FalseResult = falseResult;
}
public T TrueResult { get; set; }
public T FalseResult { get; set; }
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (TrueResult == null || FalseResult == null) return !(bool)value;
return value is bool b && b ? TrueResult : FalseResult;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (TrueResult == null || FalseResult == null) return !(bool)value;
return value is T variable && EqualityComparer<T>.Default.Equals(variable, TrueResult);
}
}
在 Xaml 中,我定义了转换器并将 True/False 值设置为所需的背景颜色:
<converters:ConfigurableBoolConverter x:Key="BackgroundColorConverter"
x:TypeArguments="x:String"
TrueResult="Color.LightGray"
FalseResult="Color.Transparent"/>
然后将 Converter 分配给自定义 ViewCell。在自定义 ViewCell 中,SelectedBackgroundColor 是使用转换器设置的。作为说明,SymbolViewCell 已经存在,用于解决作为项目一部分的图像正确刷新的不同问题
<DataTemplate>
<views:SymbolViewCell
SelectedBackgroundColor="{Binding IsChecked, Converter={StaticResource
BackgroundColorConverter}}"/>
</DataTemplate>
IsChecked 是 ItemsDataSource 的 Item 的一个属性。 ListView 已经使用了 Item 对象的集合,并且该对象已经具有 IsChecked 属性。
将 Item 对象剥离到最低限度(BindableBase 实现 IPropertyChanged 接口):
public class SymbolItem : BindableBase
{
private bool? _isChecked;
public SymbolItem(LegendInfo legendInfo, FeatureTemplate featureTemplate, ArcGISFeatureTable featureTable, IEnumerable<string> requiredFields)
{
IsChecked = false;
}
public bool? IsChecked
{
get => _isChecked;
set => SetProperty(ref _isChecked, value);
}
}
如果 ItemsDataSource 是字符串对象的集合,则此解决方案将不起作用,因为它确实需要附加属性,并且您需要绑定 SelectedItem 属性作为触发 IsChecked 属性更改的位置。但是可以创建一个简单的对象,该对象具有名称和 IsChecked 属性以进行绑定。我个人认为这个添加的代码比编写渲染器来处理事情要简单得多。
public SymbolItem SelectedSymbolItem
{
get => _selectedSymbolItem;
set
{
if ( _selectedSymbolItem != null ) _selectedSymbolItem.IsChecked = false;
SetProperty(ref _selectedSymbolItem, value);
}
}