AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / coding / 问题 / 79378482
Accepted
Kasper Sommer
Kasper Sommer
Asked: 2025-01-23 00:13:19 +0800 CST2025-01-23 00:13:19 +0800 CST 2025-01-23 00:13:19 +0800 CST

MAUI ObservableCollection 未触发转换器

  • 772

我有一个字符串的 ObservableCollection:

public ObservableCollection<string> ChallengePartImageURLs { get; } = new ObservableCollection<string>();

像这样填充/更新:

ChallengePartImageURLs.Clear();
foreach(var url in SelectedChallengePart.ImageURLs) {
    ChallengePartImageURLs.Add(url);
}

UI 更新得很好,但是当集合发生变化时,转换器不会被触发:

IsVisible="{Binding ChallengePartImageURLs, Converter={StaticResource AnyImageCheckConverter}}"

转换器正在工作,因为如果我将 ObservableCollection 更改为 ObservableProperty,它就会被完美触发。

我已尝试将 Binding 包含到 ObservableProperty 的 ConverterParameter 中,但仍然没有触发。

我是否遗漏了什么或者有没有办法触发转换器?

更新

该转换器在 XAML 中声明:

<ContentPage.Resources>
        <ResourceDictionary>
            <converters:AnyImageCheckConverter x:Key="AnyImageCheckConverter"/>
        </ResourceDictionary>
</ContentPage.Resources>

用过的:

<CollectionView ItemsSource="{Binding ChallengePartImageURLs}" IsVisible="{Binding ChallengePartImageURLs, Converter={StaticResource AnyImageCheckConverter}}">
    <CollectionView.ItemTemplate>
        <DataTemplate>
            <Label Text="{Binding .}" />
        </DataTemplate>
    </CollectionView.ItemTemplate>
</CollectionView>

转换器本身:

{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        try
        {
            if (value != null)
            {
                var list = (ObservableCollection<string>)value;
                if (list.Count > 0)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            return false;
        }
        catch (Exception ex)
        {
        }
        return false;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

仅通过清除收藏品并添加新物品才能更改收藏品。

maui
  • 2 2 个回答
  • 50 Views

2 个回答

  • Voted
  1. Best Answer
    Matt Dreiss
    2025-01-23T00:43:52+08:002025-01-23T00:43:52+08:00

    您发现,转换器未触发的主要原因是转换器仅在 PropertyChangedEvent 之后运行。当清除、添加或删除项目时,ObservableCollection 会发出NotifyCollectionChangedAction。

    对于您的用例而言,这实际上意味着触发属性更改事件,以便在您更新集合后运行转换器。这种行为方式的好处在于,您的页面不会在每次从集合中添加或删除内容时运行转换器。

    ChallengePartImageURLs.Clear();
    foreach(var url in SelectedChallengePart.ImageURLs) {
      ChallengePartImageURLs.Add(url);
    }
    PropertyChanged(this, new PropertyChangedEventArgs(nameof(ChallengePartImageURLs)));
    

    或者如果你使用MVVM 工具包,你可以简化 propteryChanged 调用

    ChallengePartImageURLs.Clear();
    foreach(var url in SelectedChallengePart.ImageURLs) {
      ChallengePartImageURLs.Add(url);
    }
    OnPropertyChanged(nameof(ChallengePartImageURLs));
    

    希望这对您有所帮助。我曾多次在我的应用中实现这种行为。我发现扩展 ObservableCollection 以添加此行为非常有益。

    • 1
  2. IV.
    2025-01-23T07:31:11+08:002025-01-23T07:31:11+08:00

    作为更迂回的替代方案IValueConverter,这种事情可以在 ViewModel 中干净利落地实现,例如通过添加 forbool和AnyImageUrl处理CollectionChanged。


    public partial class MainPage : ContentPage
    {
        public MainPage() => InitializeComponent();
    }
    

    class MainPageViewModel : INotifyPropertyChanged // Or: ObservableObject
    {
        public ObservableCollection<string> ChallengePartImageURLs { get; } = new();
        public MainPageViewModel()
        {
            ChallengePartImageURLs.CollectionChanged += (sender, e) =>
                AnyImageUrl = ChallengePartImageURLs.Any();
            IncrementCommand = new Command(OnIncrement);
            DecrementCommand = new Command(OnDecrement);
        }
    
        public bool AnyImageUrl
        {
            get => _anyImageUrl;
            set
            {
                if (!Equals(_anyImageUrl, value))
                {
                    _anyImageUrl = value;
                    OnPropertyChanged();
                }
            }
        }
        bool _anyImageUrl = default;
    
        public ICommand IncrementCommand { get; }
        private void OnIncrement(object o) => 
            ChallengePartImageURLs
            .Add($"https://www.site{ChallengePartImageURLs.Count+1}.com");
    
        public ICommand DecrementCommand { get; }
        private void OnDecrement(object o)
        {
            if(ChallengePartImageURLs.LastOrDefault() is { } exists)
            {
                ChallengePartImageURLs.Remove(exists);
            }
        }
    
        protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null) =>
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        public event PropertyChangedEventHandler? PropertyChanged;
    }
    

    最小示例

    安卓截图

    <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                 xmlns:local="clr-namespace:observe_collection_count"
                 x:Class="observe_collection_count.MainPage">
        <ContentPage.BindingContext>
            <local:MainPageViewModel/>
        </ContentPage.BindingContext>
        <ScrollView>
            <VerticalStackLayout
                Padding="30,0"
                Spacing="25">
                <Image
                    Source="dotnet_bot.png"
                    HeightRequest="185"
                    Aspect="AspectFit"
                    SemanticProperties.Description="dot net bot in a race car number eight" />
                <Label
                    Text="Subscribe to Count Demo"
                    Style="{StaticResource SubHeadline}"
                    SemanticProperties.HeadingLevel="Level2"
                    SemanticProperties.Description="Welcome to dot net Multi platform App U I" />
                <Grid ColumnDefinitions="*,*">
                    <Button
                        Grid.Column="0"
                        Text="+"
                        FontSize="Large"
                        HorizontalOptions="Fill"
                        Padding="0"
                        Margin="10,0"
                        Command="{Binding IncrementCommand}" />
                    <Button
                        Grid.Column="1"
                        Text="-"
                        Padding="0,0,0,3"
                        FontSize="Large"
                        HorizontalOptions="Fill"
                        Margin="10,0"
                        Command="{Binding DecrementCommand}"
                        IsEnabled="{Binding AnyImageUrl}"/>
                </Grid>
                <CollectionView
                    BackgroundColor="Teal"
                    ItemsSource="{Binding ChallengePartImageURLs}"
                    IsVisible="{Binding AnyImageUrl}">
                    <CollectionView.ItemTemplate>
                        <DataTemplate>
                            <Frame 
                                Padding="15"
                                Margin="10,5"
                                BackgroundColor="White"
                                CornerRadius="10"
                                HasShadow="True"
                                BorderColor="LightGray">
                                <VerticalStackLayout>
                                    <Label Text="URL"
                                           FontSize="14"
                                           TextColor="Gray"/>
                                    <Label Text="{Binding}" 
                                           FontSize="18"
                                           TextColor="Black"
                                           FontAttributes="Bold"/>
                                </VerticalStackLayout>
                            </Frame>
                        </DataTemplate>
                    </CollectionView.ItemTemplate>
                </CollectionView>
            </VerticalStackLayout>
        </ScrollView>
    </ContentPage>
    
    • 0

相关问题

  • 在图像上获取圆角

  • 如何从MAUI控件中导出并设置样式?

  • 毛伊岛地图 - 如何从位置获取地址、城市和国家/地区名称?

  • .NET Maui CollectionView,如何仅在值存在时显示值

  • ScrollView 不适用于 android 上的 collectionView 中的 ItemTemplte

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    重新格式化数字,在固定位置插入分隔符

    • 6 个回答
  • Marko Smith

    为什么 C++20 概念会导致循环约束错误,而老式的 SFINAE 不会?

    • 2 个回答
  • Marko Smith

    VScode 自动卸载扩展的问题(Material 主题)

    • 2 个回答
  • Marko Smith

    Vue 3:创建时出错“预期标识符但发现‘导入’”[重复]

    • 1 个回答
  • Marko Smith

    具有指定基础类型但没有枚举器的“枚举类”的用途是什么?

    • 1 个回答
  • Marko Smith

    如何修复未手动导入的模块的 MODULE_NOT_FOUND 错误?

    • 6 个回答
  • Marko Smith

    `(表达式,左值) = 右值` 在 C 或 C++ 中是有效的赋值吗?为什么有些编译器会接受/拒绝它?

    • 3 个回答
  • Marko Smith

    在 C++ 中,一个不执行任何操作的空程序需要 204KB 的堆,但在 C 中则不需要

    • 1 个回答
  • Marko Smith

    PowerBI 目前与 BigQuery 不兼容:Simba 驱动程序与 Windows 更新有关

    • 2 个回答
  • Marko Smith

    AdMob:MobileAds.initialize() - 对于某些设备,“java.lang.Integer 无法转换为 java.lang.String”

    • 1 个回答
  • Martin Hope
    Fantastic Mr Fox msvc std::vector 实现中仅不接受可复制类型 2025-04-23 06:40:49 +0800 CST
  • Martin Hope
    Howard Hinnant 使用 chrono 查找下一个工作日 2025-04-21 08:30:25 +0800 CST
  • Martin Hope
    Fedor 构造函数的成员初始化程序可以包含另一个成员的初始化吗? 2025-04-15 01:01:44 +0800 CST
  • Martin Hope
    Petr Filipský 为什么 C++20 概念会导致循环约束错误,而老式的 SFINAE 不会? 2025-03-23 21:39:40 +0800 CST
  • Martin Hope
    Catskul C++20 是否进行了更改,允许从已知绑定数组“type(&)[N]”转换为未知绑定数组“type(&)[]”? 2025-03-04 06:57:53 +0800 CST
  • Martin Hope
    Stefan Pochmann 为什么 {2,3,10} 和 {x,3,10} (x=2) 的顺序不同? 2025-01-13 23:24:07 +0800 CST
  • Martin Hope
    Chad Feller 在 5.2 版中,bash 条件语句中的 [[ .. ]] 中的分号现在是可选的吗? 2024-10-21 05:50:33 +0800 CST
  • Martin Hope
    Wrench 为什么双破折号 (--) 会导致此 MariaDB 子句评估为 true? 2024-05-05 13:37:20 +0800 CST
  • Martin Hope
    Waket Zheng 为什么 `dict(id=1, **{'id': 2})` 有时会引发 `KeyError: 'id'` 而不是 TypeError? 2024-05-04 14:19:19 +0800 CST
  • Martin Hope
    user924 AdMob:MobileAds.initialize() - 对于某些设备,“java.lang.Integer 无法转换为 java.lang.String” 2024-03-20 03:12:31 +0800 CST

热门标签

python javascript c++ c# java typescript sql reactjs html

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve