You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 07:36:19