我知道这个问题在很久以前就已经得到了回答,但我想我会在这里为任何可能偶然发现这个问题的人添加更多信息,以寻找一种对 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();
}
}
如果提供的参数计算结果为真,转换器只会返回适当的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;
}
}
}