简体   繁体   English

ViewModel 中的 ObservableCollection 在过滤后不呈现 - Maui/WinUI

[英]ObservableCollection in ViewModel doesn't render after filtering in - Maui/WinUI

I'm playing around with a MAUI application, and have an ObservableCollection bound to a FlexLayout in Xaml ContentPage .我正在玩一个 MAUI 应用程序,并且在 Xaml ContentPage中有一个绑定到FlexLayoutObservableCollection The collection displays fine initially, but I've added some filtering logic, and after filtering the collection fails to render.该集合最初显示良好,但我添加了一些过滤逻辑,过滤后集合无法呈现。 This appears to only occur on WinUI, as it filters and renders correctly on the Android emulator, I've not yet set up an IoS simulator.这似乎只发生在 WinUI 上,因为它在 Android 模拟器上正确过滤和呈现,我还没有设置 IoS 模拟器。 The issue also appears to be specific to the FlexLayout, as when I change the flex layout to a ListView, it filters and renders correctly as well.该问题似乎也特定于 FlexLayout,因为当我将 flex 布局更改为 ListView 时,它也会正确过滤和呈现。

Any advice on how to fix this and continue to use the flex layout would be greatly appreciated.任何有关如何解决此问题并继续使用 flex 布局的建议将不胜感激。

The ContentPage内容页面

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:Views="clr-namespace:Views"
             x:Class="Collection"
             Title="Collection">
    <ContentPage.Content>
        <ScrollView>
            <StackLayout>
                <!--Search-->
                <Views:SearchAndFilterView x:Name="SearchView"
                                           Placeholder="Search collection..." 
                                           TextChanged="SearchView_TextChanged"/>


                <!-- Collection-->
                <FlexLayout x:Name="CollectionFlexLayout"
                            BindableLayout.ItemsSource="{Binding Collection}"
                            HorizontalOptions="CenterAndExpand"
                            Wrap="Wrap">
                    <BindableLayout.ItemTemplate>
                        <DataTemplate>
                            <Views:CollectionCardView 
                                                      IconImageSource="{Binding Image}"
                                                      CardTitle="{Binding Name}"
                                                      Designer="{Binding Designers[0]}"
                                                      Publisher="{Binding Publishers[0]}"
                                                      YearPublished="{Binding YearPublished}"
                                                      PlayCount="{Binding NumPlays}"
                                                      MaxPlayers="{Binding MaxPlayers}"
                                                      MinPlayers="{Binding MinPlayers}"
                                                      PlayTime="{Binding PlayTime}"
                                                      MinAge="{Binding MinAge}"/>
                        </DataTemplate>
                    </BindableLayout.ItemTemplate>                    
                </FlexLayout>
            </StackLayout>
        </ScrollView>
    </ContentPage.Content>
</ContentPage>


The ContentPage code behind后面的 ContentPage 代码

public partial class Collection : ContentPage
{
    public ICollectionViewModel collectionViewModel;

    public Collection()
    {
        InitializeComponent();
        Init();
        InitAsync();
    }

    public void Init()
    {
        collectionViewModel = BootStrapper.Resolve<ICollectionViewModel>();
        BindingContext = collectionViewModel;
    }

    public async void InitAsync()
    {
        await collectionViewModel.GetCollection("testAcct");
    }

   

    private void SearchView_TextChanged(object sender, TextChangedEventArgs e)
    {
        collectionViewModel.FilterCollection(SearchView.SearchText, SearchView.AgeText, SearchView.PlayerCountText, SearchView.PlayTimeText);
    }

The ViewModel:视图模型:

public class CollectionViewModel : ViewModelBase, ICollectionViewModel
    {
        private readonly ILogger _logger;
        private readonly ICollectionHandler _collectionHandler;
        private readonly ICollectionHelper _collectionHelper;
        private readonly IThingHandler _thingHandler;

        private ObservableCollection<CollectionPageItem> _collection = new();
        private IEnumerable<CollectionPageItem> _fullCollection;
        private bool _isBusy;

        public CollectionViewModel(ILogger logger, ICollectionHandler collectionHandler, IThingHandler thingHandler,
            ICollectionHelper collectionHelper)
        {
            _logger = logger;
            _collectionHandler = collectionHandler;
            _collectionHelper = collectionHelper;
            _thingHandler = thingHandler;
        }

        /// <summary>
        /// True if the ViewModel is querying data.
        /// </summary>
        public bool IsBusy
        {
            get => _isBusy;
            set { _isBusy = value; OnPropertyChanged(nameof(IsBusy)); }
        }

        /// <summary>
        /// The Collection to display.
        /// </summary>
        public ObservableCollection<CollectionPageItem> Collection
        {
            get { return _collection; }
            set { _collection = value; OnPropertyChanged(nameof(Collection)); }
        }

        /// <summary>
        /// Loads the <see cref="Collection"/> property for the given user.
        /// </summary>
        /// <param name="userName">The user to load a collection for.</param>
        public async Task GetCollection(string userName)
        {
            IsBusy = true;

            try
            {
                var collectionResponse = await _collectionHandler.GetCollectionByUserName(userName);
                var things = await _thingHandler.GetThingsById(collectionResponse.Item.Items.Select(x => x.Id).ToList());

                _fullCollection = _collectionHelper.CoalesceCollectionData(collectionResponse.Item.Items, things.Item.Things);
                Collection = _fullCollection.ToObservableCollection();

            }
            catch (Exception ex)
            {
                _logger.Error(ex.Message);
            }
            finally
            {
                IsBusy = false;
            }
        }

        //TODO: Make this work
        public void FilterCollection(string name, string age, string playercount, string time)
        {
            IEnumerable<CollectionPageItem> query = _fullCollection;

            if (!string.IsNullOrWhiteSpace(name))
            {
                query = query.Where(x => x.Name.ToLower().Contains(name));
            }

            if (int.TryParse(age, out int parsedAge))
            {
                query = query.Where(x => x.MinAge >= parsedAge);
            }

            if (int.TryParse(playercount, out int parsedPlayercount))
            {
                query = query.Where(x => x.MinPlayers >= parsedPlayercount);
            }

            if (int.TryParse(time, out int parsedTime))
            {
                query = query.Where(x => x.PlayTime <= parsedTime);
            }

            Collection = query.ToObservableCollection();
        }
    }

FlexLayout seems to have some spacing issues in Windows. FlexLayout 在 Windows 中似乎存在一些间距问题。 A workaround is setting HorizontalOptions="Center" for the FlexLayout and giving to it HeightRequest and WidthRequest values.一种解决方法是为 FlexLayout 设置HeightRequest ​​ntalOptions HorizontalOptions="Center"并为其提供FlexLayoutWidthRequest值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM