简体   繁体   中英

Why isn't my ListView displaying any content when using grouping?

I am attempting to make a simple filter menu using a ListView with Grouping enabled. Currently I'm doing this by generating a modal page from the parent page, which is passed an object I need to populate the menu, and which contains a few buttons plus the list page. I am unable to get even the simplest grouping ListView appearing however. I've followed the tutorial here to get to where I'm at.

I'll include the XAML, codebehind, and ViewModel for the Filter Page, as well as the models described in the tutorial for the filter groups and filter options. Please know that although the page is passed an object in my code, I'm not using it in any way yet with what I'm posting here.

XAML

    <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             mc:Ignorable="d"
             x:Class="MyProject.Views.FilterMenu">
        <ContentPage.Content>

            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="*"/>
                    <RowDefinition Height="Auto"/>
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition />
                    <ColumnDefinition />
                </Grid.ColumnDefinitions>

                <Button Text="Close"
                        Grid.Column="0"
                        Grid.Row="0"
                        HorizontalOptions="FillAndExpand"
                        Clicked="CloseButton_OnClicked"/>

                <Button Text="Clear Filter"
                        Grid.Column="1"
                        Grid.Row="0"
                        HorizontalOptions="FillAndExpand"
                        Clicked="ClearButton_OnClicked"/>

                <Label Text="Filter By"
                       Grid.Column="0"
                       Grid.ColumnSpan="2"
                       Grid.Row="1"
                       VerticalOptions="FillAndExpand" 
                       HorizontalOptions="StartAndExpand"
                       HorizontalTextAlignment="Start"/>


                <StackLayout Grid.Column="0"
                             Grid.ColumnSpan="2"
                             Grid.Row="2">
                    <ListView ItemsSource="{Binding FilterOptionList}"
                              IsGroupingEnabled="True"
                              GroupDisplayBinding="{Binding Name}">
                        <ListView.ItemTemplate>
                            <DataTemplate>
                                <TextCell Text="{Binding Name}"></TextCell>
                            </DataTemplate>
                        </ListView.ItemTemplate>
                    </ListView>
                </StackLayout>
                <Button
                    Text="Apply Filter"
                    Grid.Column="0"
                    Grid.ColumnSpan="2"
                    Grid.Row="3"
                    Clicked="ApplyFilterButton_OnClicked"/>
            </Grid>

        </ContentPage.Content>
    </ContentPage>

Code Behind

using System;
    using MyProject.Models;
    using MyProject.ViewModels;
    using MvvmHelpers;
    using Xamarin.Forms;
    using Xamarin.Forms.Xaml;
    
    namespace MyProject.Views
    {
        [XamlCompilation(XamlCompilationOptions.Compile)]
        public partial class FilterMenu : ContentPage
        {
            public FilterMenu(ObservableRangeCollection<Unit> units)
            {
                InitializeComponent();
                BindingContext = new FilterMenuViewModel(Navigation, units);
            }
    
            private void CloseButton_OnClicked(object sender, EventArgs e)
            {
                (BindingContext as FilterMenuViewModel)?.Close();
            }
    
            private void ClearButton_OnClicked(object sender, EventArgs e)
            {
                (BindingContext as FilterMenuViewModel)?.ClearFilter();
            }
    
            private void ApplyFilterButton_OnClicked(object sender, EventArgs e)
            {
                (BindingContext as FilterMenuViewModel)?.ApplyFilter();
            }
        }
    }

ViewModel

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using MyProject.Annotations;
using MyProject.Models;
using Microsoft.Extensions.Options;
using Xamarin.Forms;

namespace MyProject.ViewModels
{
    public class FilterMenuViewModel : INotifyPropertyChanged
    {
        public ObservableCollection<Unit> Units { get; private set; }
        public ObservableCollection<FilterOptionGroup> FilterOptionList = new ObservableCollection<FilterOptionGroup>();
        private readonly INavigation _navigation;
        public event PropertyChangedEventHandler PropertyChanged;       

        public FilterMenuViewModel(INavigation navigation, ObservableCollection<Unit> units )
        {
            _navigation = navigation;
            this.Units = units;

            PopulateCategories();
            FilterOptionList.Add(new FilterOptionGroup("Group One", new []
            {
                new FilterOption
                {
                    Name = "Option One", IsFiltered = false
                },
                new FilterOption
                {
                    Name = "Option One", IsFiltered = false
                }
            }));

            FilterOptionList.Add(new FilterOptionGroup("Group Two", new[]
            {
                new FilterOption
                {
                    Name = "Option One", IsFiltered = false
                },
                new FilterOption
                {
                    Name = "Option Two", IsFiltered = false
                },
                new FilterOption
                {
                    Name = "Option Three", IsFiltered = false
                }
            }));
        }

        [NotifyPropertyChangedInvocator]
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));

        }

        public async void Close()
        {
            await _navigation.PopModalAsync();
        }

        public void ClearFilter()
        {
            Debug.WriteLine("Clear Filter Clicked.");
        }

        public void ApplyFilter()
        {
            Debug.WriteLine("Apply Filter Clicked.");
        }
    }
}

Filter Option GROUP Collection

using System.Collections.ObjectModel;
using System.Text;

namespace MyProject.Models
{
    public class FilterOptionGroup : ObservableCollection<FilterOption>
    {
        public string Name { get; private set; }

        public FilterOptionGroup(string name)
            : base()
        {
            Name = name;
        }

        public FilterOptionGroup(string name, IEnumerable<FilterOption> source)
            : base(source)
        {
            Name = name;
        }
    }
}

Filter Option Class

using System;
using System.Collections.Generic;
using System.Text;

namespace DormRemote.Models
{
    public class FilterOption
    {
        private string _name;
        private bool _isFiltered;

        public string Name
        {
            get { return _name; }
            set { _name = value; }
    }

        public bool IsFiltered
        {
            get => _isFiltered;
            set => _isFiltered = value;
        }
    }
}

As far as I can tell my binding is set up properly because my buttons print the corresponding debug text, and if I replace the current ListView with a simple ListView without Grouping enabled, and bind it to a simple List it displays correctly.

Additionally, I have tested that the FilterOptionList is being populated correctly as I have printed out the contents of each of its groups using debug code.

I'm not sure if I'm just missing something or if the implementation from this tutorial just doesn't work. Any assistance would be appreciated.

you are binding to FilterOptionList which is not a public property of your VM. You can only bind to public properties.

C# properties have a get; and/or set; Otherwise they are just fields.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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