ListView 中第一个项目的 WinUI 复选框不反映来自服务器同步的绑定属性更改

问题描述 投票:0回答:1

描述:

我在 WinUI 3 应用程序中遇到奇怪的行为,其中 ListView 显示项目集合。每个项目模板中的复选框都绑定到名为 IsComplete 的 bool 属性。这是一个多客户端、服务器同步的应用程序,其中数据更改可以从不同的客户端发生并通过服务器同步。

详情:

  • 当我选中或取消选中 WinUI 应用程序中任何项目的复选框时,它可以正常工作并按预期更新 IsComplete 属性。
  • 当对另一个客户端中的项目进行更改,并且这些更改同步到服务器,然后拉入此 WinUI 应用程序时,所有项目都会在绑定集合和 UI 中正确反映更新 - ListView 中的第一个项目除外.
  • 即使绑定数据已正确更新(通过调试步骤进行验证),第一项的 CheckBox 和 TextBlock 在服务器同步后不会进行视觉更新以匹配 IsComplete 的新值。

相关代码

XAML
<ListView
    Grid.Row="1"
    Margin="10"
    ItemsSource="{x:Bind ViewModel.Items}"
    ScrollViewer.VerticalScrollBarVisibility="Auto">
    <ListView.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal">
                <CheckBox
                    Margin="10"
                    Command="{Binding ViewModel.EditItemCommand, ElementName=ThisPage}"
                    CommandParameter="{Binding Id}"
                    Content="{Binding Title}"
                    IsChecked="{Binding IsComplete}" />
                <TextBlock Margin="10" Text="Checked: " />
                <TextBlock Text="{Binding IsComplete}" />
            </StackPanel>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>
绑定收藏
[ObservableProperty]
private ConcurrentObservableCollection<TodoItem> items = [];
刷新命令
[RelayCommand]
public async Task RefreshItemsAsync(CancellationToken cancellationToken = default)
{
    try
    {
        IsRefreshing = true;

        // Synchronize data with the remote service (if any).
        await service.SynchronizeAsync(cancellationToken);

        // Pull all items from the database.
        IEnumerable<TodoItem> itemsFromDatabase = await service.TodoItems.OrderBy(item => item.Id).ToListAsync(cancellationToken);

        // Replace all the items in the collection.
        Items.ReplaceAll(itemsFromDatabase);
        //Items.Clear();
        //_ = Items.AddRange(itemsFromDatabase);
    }
    catch (Exception ex)
    {
        NotificationHandler?.Invoke(this, new NotificationEventArgs(ex.GetType().Name, ex.Message, true));
    }
    finally
    {
        IsRefreshing = false;
        NotificationHandler?.Invoke(this, new NotificationEventArgs("Items Refreshed", "", false));
    }
}
数据模型
public class TodoItem : OfflineClientEntity
{
    private bool _isComplete = false;
    public string Title { get; set; } = string.Empty;
    public bool IsComplete { get; set; } = false;


    public override string ToString()
        => JsonSerializer.Serialize(this);
}

using System;
using System.ComponentModel.DataAnnotations;

namespace TodoApp.WinUI3.Database;

/// <summary>
/// An abstract class for working with offline entities.
/// </summary>
public abstract class OfflineClientEntity
{
    [Key]
    public string Id { get; set; }
    public DateTimeOffset? UpdatedAt { get; set; }
    public string Version { get; set; }
    public bool Deleted { get; set; }
}

观察到的行为

  • 直接在 UI 中单击复选框会更新 IsComplete 并正确反映更改。
  • 当另一个客户端修改第一个项目并同步更改,并且这些更改被拉入 WinUI 应用程序时,第一个项目的绑定 IsComplete 属性会正确更新(使用 TextBlock 验证),但 CheckBox 视觉状态不会反映这一点改变。
  • 列表中的所有其他项目在 UI 中直接修改以及从服务器同步更新时均按预期运行。
c# .net xaml winui-3
1个回答
0
投票

首先,我不熟悉

ConcurrentObservableCollection
,所以我假设它基于ObservableCollection

现在,当您在待办事项中应用更改时,通常需要实现 INotifyPropertyChanged。您可以自己完成,但由于您使用的是 CommunityToolkit.Mvvm,因此您可以为 TodoItem 创建一个

ObservableObject
基类,或者只是用包装类包装它。

© www.soinside.com 2019 - 2024. All rights reserved.