.NET MAUI中ObservableCollection属性变更未触发DataTrigger无UI更新
CollectionView中DataTrigger未触发的解决方案
问题场景
点击CollectionView内的按钮时,期望通过DataTrigger切换按钮背景色,但UI无任何变化,DataTrigger未触发。
相关代码
XAML代码
<CollectionView ItemsSource="{Binding Categories}" VerticalScrollBarVisibility="Never" HorizontalScrollBarVisibility="Never" VerticalOptions="Center"> <CollectionView.ItemsLayout> <LinearItemsLayout Orientation="Horizontal" ItemSpacing="3" /> </CollectionView.ItemsLayout> <CollectionView.ItemTemplate> <DataTemplate x:DataType="model:Category"> <Button Padding="10, 5" Margin="10, 15, 0, 10" BorderColor="Transparent" Background="{Binding Source={StaticResource Gray300}, ConverterParameter=0.4, Converter={StaticResource ColorToRGBAColor}}" VerticalOptions="Center" Text="{Binding Name}" Command="{Binding Source={x:Reference TaskListPage},Path=BindingContext.CategorySelectedCommand}" CommandParameter="{Binding .}"> <Button.Triggers> <DataTrigger TargetType="Button" Binding="{Binding IsActive}" Value="True"> <Setter Property="Background" Value="Red" /> </DataTrigger> </Button.Triggers> </Button> </DataTemplate> </CollectionView.ItemTemplate> </CollectionView>
ViewModel代码
public partial class TaskListViewModel : ObservableObject { [ObservableProperty] private ObservableCollection<Category> categories; public IRelayCommand<Category> CategorySelectedCommand { get; set; } public TaskListViewModel() { categories = new ObservableCollection<Category>(); categories.Add(new Category { Name = "Work", IsActive = true }); categories.Add(new Category { Name = "Personal", IsActive = false }); categories.Add(new Category { Name = "Wishlist", IsActive = false }); CategorySelectedCommand = new RelayCommand<Category>(CategorySelected); } private void CategorySelected(Category category) { Categories.All(c => { c.IsActive = false; return true; }); var categoryToActivate = Categories.SingleOrDefault(x => x == category); if (categoryToActivate is null) { return; } categoryToActivate.IsActive = true; OnPropertyChanged(nameof(Categories)); } }
核心原因
Category类未实现INotifyPropertyChanged接口,修改IsActive属性时无法通知UI更新。ObservableCollection仅监听集合的增、删、替换操作,不负责监听集合内元素的属性变化。ViewModel中调用OnPropertyChanged(nameof(Categories))属于无效操作,无法触发元素属性变更的UI更新。
解决方案
1. 让Category类实现属性变更通知
使用CommunityToolkit.Mvvm的ObservableObject简化实现:
using CommunityToolkit.Mvvm.ComponentModel; namespace YourProjectNamespace.Model { public partial class Category : ObservableObject { [ObservableProperty] private string name; [ObservableProperty] private bool isActive; } }
如果不使用工具包,也可以手动实现INotifyPropertyChanged接口:
using System.ComponentModel; using System.Runtime.CompilerServices; namespace YourProjectNamespace.Model { public class Category : INotifyPropertyChanged { private string _name; private bool _isActive; public string Name { get => _name; set { _name = value; OnPropertyChanged(); } } public bool IsActive { get => _isActive; set { _isActive = value; OnPropertyChanged(); } } public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } }
2. 移除ViewModel中无效的集合变更通知
修改CategorySelected方法,删除OnPropertyChanged(nameof(Categories)):
private void CategorySelected(Category category) { foreach (var c in Categories) { c.IsActive = false; } category.IsActive = true; // 移除此行,无需通知集合整体变化 // OnPropertyChanged(nameof(Categories)); }
完成上述修改后,点击按钮时IsActive属性变更会触发UI更新,DataTrigger将正常生效切换按钮背景色。
内容的提问来源于stack exchange,提问作者Jurijus Ambros
相关产品推荐
相关产品推荐

