我发现最简单的方法是不使用 SelectionMode 或 SelectedItem,而是使用 Tapped 事件。从这里你可以得到“选定的项目”。
然后,我在 ViewModel 中设置一个绑定属性,如果我想选择它,View 将使用该属性更改 ListView 中所选项目的背景。要有效地做到这一点,您的 ListView 需要绑定到 ViewModels 的 ObservableCollection(或实现 INotifyPropertyChanged 的类)。
这里有一些粗略的代码来说明我的意思:
在 Xaml 查看代码
<ListView
ItemsSource ="{Binding Values}"
ItemTapped="OnItemTapped"
HasUnevenRows="True"
RefreshAllowed="True"
SelectionMode="None"
>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid RowSpacing="0" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100*"/>
<ColumnDefinition Width="40"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="30*"/>
</Grid.RowDefinitions>
<BoxView Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="2" BackgroundColor="{StaticResource Blue}" IsVisible="{Binding IsSelected}" />
<Label Grid.Column="0" Grid.Row="0" HorizontalTextAlignment="Center" VerticalOptions="Center" Text="{Binding Destination}"/>
<Label Grid.Column="1" Grid.Row="0" HorizontalTextAlignment="Start" VerticalOptions="Center" Text="{Binding Value}"/>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
在后面的代码中:
private void OnItemTapped(object sender, ItemTappedEventArgs e)
{
var param = (ValueViewModel)e.Item;
if (((SourceViewModel)BindingContext).SelectValueCommand.CanExecute(param))
{
((SourceViewModel)BindingContext).SelectValueCommand.Execute(param);
}
}
然后使用这些类——第一个是视图的BindingContext
public class SourceViewModel:INotifyPropertyChanged
{
public SourceViewModel (List<ValueViewModel> list)
{
SelectValueCommand = new Command<ValueViewModel>((value) => ExecuteSelectValueCommand(value), (value)=>!IsBusy);
}
private ObservableCollection<ValueViewModel> _values = new ObservableCollection<ValueViewModel>();
private bool _isSelected;
private sring _description;
public ICommand SelectValueCommand;
public bool IsBusy{get;set;}
public ObservableCollection<ValueViewModel> Values
{
get=>_values;
set
{
_values = value;
OnPropertyChanged(nameof(Values));
}
}
public void ExecuteSelectValueCommand(ValueViewModel value)
{
if(IsBusy) return;
item.IsSelected = CanValueBeSelected(value);
}
private bool CanValueBeSelected(ValueViewModel value)
{
var result = false;
//Some logic to determine if it can be selected
return result;
}
#region INotifyPropertyChanged implementation
// ...
#endregion
}
public class ValueViewModel:INotifyPropertyChanged
{
public ValueViewModel (string description, int value)
{
Description = description;
Value = value;
}
private int _value;
private bool _isSelected;
private sring _description;
public int Value
{
get=>_value;
set
{
_value=value;
OnPropertyChanged(nameof(Value));
}
}
public bool IsSelected
{
get=> _isSelected;
set
{
_isSelected= value;
OnPropertyChanged(nameof(IsSelected));
}
}
public string Description
{
get=> _description;
set
{
_description= value;
OnPropertyChanged(nameof(Description));
}
}
#region INotifyPropertyChanged implementation
// ...
#endregion
}