簡體   English   中英

ViewModel 中的 ObservableCollection 在過濾后不呈現 - Maui/WinUI

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

我正在玩一個 MAUI 應用程序,並且在 Xaml ContentPage中有一個綁定到FlexLayoutObservableCollection 該集合最初顯示良好,但我添加了一些過濾邏輯,過濾后集合無法呈現。 這似乎只發生在 WinUI 上,因為它在 Android 模擬器上正確過濾和呈現,我還沒有設置 IoS 模擬器。 該問題似乎也特定於 FlexLayout,因為當我將 flex 布局更改為 ListView 時,它也會正確過濾和呈現。

任何有關如何解決此問題並繼續使用 flex 布局的建議將不勝感激。

內容頁面

<?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>


后面的 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);
    }

視圖模型:

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 在 Windows 中似乎存在一些間距問題。 一種解決方法是為 FlexLayout 設置HeightRequest ​​ntalOptions HorizontalOptions="Center"並為其提供FlexLayoutWidthRequest值。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM