Xamarin CollectionView绑定ObservableCollection出现数字消失异常
解决CollectionView绑定ObservableCollection时数字随机消失的问题
问题根源
- 模型
Case未实现INotifyPropertyChanged,属性变更无法通知视图更新 - 通过替换集合中整个
Case对象的方式更新,触发CollectionView的视图复用逻辑,导致绑定错乱 - 视图中
VisualState的Selected状态设置与手动修改背景色存在冲突
解决方案步骤
1. 让Case模型实现INotifyPropertyChanged
修改模型类,确保属性变更时能通知视图刷新:
public class Case : INotifyPropertyChanged { private int _id; private string _colorToPrint; public int Id { get => _id; set { _id = value; OnPropertyChanged(nameof(Id)); } } public string ColorToPrint { get => _colorToPrint; set { _colorToPrint = value; OnPropertyChanged(nameof(ColorToPrint)); } } public Case(int id, string color) { Id = id; ColorToPrint = color; } public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }
2. 修改ViewModel的选中逻辑,直接更新现有对象属性
无需新建Case对象替换集合项,直接修改选中项的颜色属性即可:
private void OnSelectionChanged() { if (SelectedCase == null) return; // 直接修改选中对象的颜色属性,而非替换整个对象 SelectedCase.ColorToPrint = "Green"; // 可选:取消选中状态,避免视觉冲突 SelectedCase = null; }
3. 优化视图的VisualState配置
调整Selected状态的设置,避免和绑定的背景色冲突:
<Frame Padding="2" BackgroundColor="Transparent"> <VisualStateManager.VisualStateGroups> <VisualStateGroup Name="CommonStates"> <VisualState Name="Normal" /> <VisualState Name="Selected"> <VisualState.Setters> <!-- 设置选中时的边框效果,不覆盖背景色 --> <Setter Property="BorderColor" Value="DarkGreen"/> </VisualState.Setters> </VisualState> </VisualStateGroup> </VisualStateManager.VisualStateGroups> <Frame BorderColor="Black" MinimumHeightRequest="20" CornerRadius="5" BackgroundColor="{Binding ColorToPrint}"> <Label Text="{Binding Id}" TextColor="Black" FontAttributes="Bold" FontSize="15" HorizontalOptions="Center" VerticalOptions="Center"/> </Frame> </Frame>
4. 确保CollectionView的双向绑定
显式声明SelectedItem的双向绑定(默认双向,显式声明更清晰):
<CollectionView ItemsSource="{Binding Cases}" SelectionMode="Single" SelectedItem="{Binding SelectedCase, Mode=TwoWay}" SelectionChangedCommand="{Binding SelectionChangedCommand}" Grid.Column="0" Grid.Row="0" ItemsLayout="VerticalGrid, 6" Margin="20">
逻辑说明
- 实现
INotifyPropertyChanged后,属性变更会直接通知视图刷新,避免依赖CollectionView复用机制的偶然更新 - 直接修改现有对象属性而非替换集合项,能避免视图复用导致的绑定错乱问题
- 调整VisualState配置,消除手动修改背景色与控件选中状态的视觉冲突
内容的提问来源于stack exchange,提问作者Benjamin Dagbert
相关产品推荐
相关产品推荐

