在分组的ListView中显示组标题

时间:2019-01-16 19:32:46

标签: c# xaml uwp

ListView中显示组标题,而不是按排序键。

您好,我正在为Windows 10移动版开发UWP应用程序。 我有一个ListView,其中包含SQLite数据库中的项目。每个项目都属于一个类别,ListView按类别分组。在显示中,组的标题是类别的名称,并且这些类别按字母顺序排序。 XAML代码的主要元素是:

<ListView x:Name="listBoxobj" 
    ItemsSource="{Binding Source={StaticResource cvsource}}"
    BorderBrush="#FF141EE4" 
    Margin="0,0,0,0"
    HorizontalAlignment="Stretch"
    SelectionMode="None"
    IsItemClickEnabled="True"
    RightTapped="listBoxobj_RightTapped"
    SelectedItem="{Binding Name}">
    <ListView.ItemTemplate>
        <DataTemplate>
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="20*" />
                    <ColumnDefinition Width="3*" />
                </Grid.ColumnDefinitions>
                <StackPanel Orientation="Horizontal">
                    <TextBlock x:Name="NameTxt" Grid.Column="0" Margin="0,0,0,0" TextWrapping="Wrap" Text="{Binding NomArt}" FontSize="20" Foreground="White"/>
                    <TextBlock x:Name="QteArtTxt" Grid.Column="0" Margin="20,0,0,0" TextWrapping="Wrap" Text="{Binding QuantArt}" FontSize="20" Foreground="DarkGray" FontStyle="Italic"/>
                    <TextBlock x:Name="UniteMesureTxt" Grid.Column="0" Margin="10,0,0,0" TextWrapping="Wrap" Text="{Binding UnitArt}" FontSize="20" Foreground="DarkGray" FontStyle="Italic"/>
                </StackPanel>
                <Button x:Name="btnPanier" Grid.Column="1" Height="35" Width="35" Tag="{Binding}" Click="btnPanier_Click">
                    <Button.Background>
                        <ImageBrush ImageSource="/Assets/Images/icone_caddie_40x40.png" Stretch="UniformToFill">
                        </ImageBrush>
                    </Button.Background>
                </Button>
                <TextBlock x:Name="NoteTxt" Grid.Row="2" Margin="0,20,0,0" TextWrapping="Wrap" Text="{Binding NoteArt}" FontSize="16" Foreground="DarkGray" FontStyle="Italic"/>
            </Grid>
        </DataTemplate>
    </ListView.ItemTemplate>

    <ListView.GroupStyle>
        <GroupStyle>
            <GroupStyle.HeaderTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Key}" Foreground="CadetBlue" FontSize="18" />
                </DataTemplate>
            </GroupStyle.HeaderTemplate>
        </GroupStyle>
    </ListView.GroupStyle>

    <ListView.ItemContainerStyle>
        <Style TargetType="ListViewItem">
            <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
        </Style>
    </ListView.ItemContainerStyle>

    <ListView.Resources>
        <MenuFlyout x:Name="MenuFlyoutContext" x:Key="FlyoutBaseKey">
            <MenuFlyoutItem x:Name="MFSubMenu1" x:Uid="MenuFlyoutModif" Click="MFSubMenu1_Click"/>
            <MenuFlyoutItem x:Name="MFSubMenu2" x:Uid="MenuFlyoutDelete" Click="MFSubMenu2_Click"/>
        </MenuFlyout>
    </ListView.Resources>

    <FlyoutBase.AttachedFlyout>
        <StaticResource ResourceKey="FlyoutBaseKey"/>
    </FlyoutBase.AttachedFlyout>
</ListView>

下面是显示ListView的代码:

protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        var resourceLoader = Windows.ApplicationModel.Resources.ResourceLoader.GetForCurrentView();
        currentListeAchat = e.Parameter as string;
        textBlock.Text = resourceLoader.GetString("PanierTitre") + " " + currentListeAchat;
        //
        Achats = new ObservableCollection<Achat>();
        AchatsIn = new ObservableCollection<Achat>();
        //
        DB_PanierList = dbpaniers.GetAllPaniers();
        var query = DB_PanierList.Where(x => x.NomListe == currentListeAchat & x.InOut == "Out");
        //
        foreach (var item in query)
        {
            string nomart = item.Name;
            string quantart = item.QteArt;
            string noteart = item.Note;
            string catart = item.NomCat;
            int catorder = item.OrdreCat; 
            string unitart = item.UniteMesure;
            string inout = item.InOut;
            Achats.Add(new Achat()
            {
                NomArt = nomart,
                QuantArt = quantart,
                NoteArt = noteart,
                CatArt = catart,
                CatOrder = catorder,
                UnitArt = unitart,
                InOut = inout
            });
        }
        //
        _groupingCollection = new ObservableGroupingCollection<string, Achat>(Achats);
        _groupingCollection.ArrangeItems(new CatSorter(), (x => x.CatOrder.ToString()));
        GroupedAchats = _groupingCollection.Items;
        cvsource.Source = GroupedAchats;
        //
        //
        var queryin = DB_PanierList.Where(x => x.NomListe == currentListeAchat & x.InOut == "In");
        //
        foreach (var item in queryin)
        {
            string nomart = item.Name;
            string quantart = item.QteArt;
            string noteart = item.Note;
            string catart = item.NomCat;
            int catorder = item.OrdreCat;
            string unitart = item.UniteMesure;
            string inout = item.InOut;
            AchatsIn.Add(new Achat()
            {
                NomArt = nomart,
                QuantArt = quantart,
                NoteArt = noteart,
                CatArt = catart,
                CatOrder = catorder,
                UnitArt = unitart,
                InOut = inout
            });
        }
        //
        _groupingCollectionIn = new ObservableGroupingCollection<string, Achat>(AchatsIn);
        _groupingCollectionIn.ArrangeItems(new CatSorter(), (x => x.CatArt));
        GroupedAchatsIn = _groupingCollectionIn.Items;
        cvsourceIn.Source = GroupedAchatsIn;
        //
        // Register for hardware and software back request from the system
        SystemNavigationManager systemNavigationManager = SystemNavigationManager.GetForCurrentView();
        systemNavigationManager.BackRequested += OnBackRequested;
    }

以及类ObservableGroupingCollection:

public class ObservableGroupingCollection<K, T> where K : IComparable
{
    public ObservableGroupingCollection(ObservableCollection<T> collection)
    {
        _rootCollection = collection;
        _rootCollection.CollectionChanged += _rootCollection_CollectionChanged;
    }

    ObservableCollection<T> _rootCollection;
    private void _rootCollection_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        HandleCollectionChanged(e);
    }

    ObservableCollection<Grouping<K, T>> _items;
    public ObservableCollection<Grouping<K, T>> Items
    {
        get { return _items; }
    }

    IComparer<T> _sortOrder;
    Func<T, K> _groupFunction;

    public void ArrangeItems(IComparer<T> sortorder, Func<T, K> group)
    {
        _sortOrder = sortorder;
        _groupFunction = group;

        var temp = _rootCollection
            .OrderBy(i => i, _sortOrder)
            .GroupBy(_groupFunction)
            .ToList()
            .Select(g => new Grouping<K, T>(g.Key, g));

        _items = new ObservableCollection<Grouping<K, T>>(temp);

    }

    private void HandleCollectionChanged(NotifyCollectionChangedEventArgs e)
    {
        if (e.Action == NotifyCollectionChangedAction.Add)
        {
            var item = (T)(e.NewItems[0]);
            var value = _groupFunction.Invoke(item);

            // find matching group if exists
            var existingGroup = _items.FirstOrDefault(g => g.Key.Equals(value));

            if (existingGroup == null)
            {
                var newlist = new List<T>();
                newlist.Add(item);

                // find first group where Key is greater than this key
                var insertBefore = _items.FirstOrDefault(g => ((g.Key).CompareTo(value)) > 0);
                if (insertBefore == null)
                {
                    // not found - add new group to end of list
                    _items.Add(new Grouping<K, T>(value, newlist));
                }
                else
                {
                    // insert new group at this index
                    _items.Insert(_items.IndexOf(insertBefore), new Grouping<K, T>(value, newlist));
                }
            }
            else
            {
                // find index to insert new item in existing group
                int index = existingGroup.ToList().BinarySearch(item, _sortOrder);
                if (index < 0)
                {
                    existingGroup.Insert(~index, item);
                }
            }
        }
        else if (e.Action == NotifyCollectionChangedAction.Remove)
        {
            var item = (T)(e.OldItems[0]);
            var value = _groupFunction.Invoke(item);

            var existingGroup = _items.FirstOrDefault(g => g.Key.Equals(value));

            if (existingGroup != null)
            {
                // find existing item and remove
                var targetIndex = existingGroup.IndexOf(item);
                existingGroup.RemoveAt(targetIndex);

                // remove group if zero items
                if (existingGroup.Count == 0)
                {
                    _items.Remove(existingGroup);
                }
            }
        }

    }
}

可以看出,标头通常由以下行生成:

<TextBlock Text="{Binding Key}" Foreground="CadetBlue" FontSize="18" />

我希望用户能够根据他的选择订购类别。因此,我添加了一个OrderCat(int)字段,该字段将类别从1编号为(类别编号)。在后面的代码中,我将ListView不在Category字段上分组,而是在OrderCat上分组,并且效果很好(这些分组按选择的顺序出现,而不是按字母顺序出现)。唯一的问题是由于{Binding Key},标题显示的是数字(OdreCat),而不是类别的名称。如何显示与数字相对应的名称?

有人可以帮我吗?

1 个答案:

答案 0 :(得分:0)

对于所有试图帮助我的人感到抱歉,但是我无法回答,因为我没有提供重要要素:CatSorter类。 那是必须进行更改的地方。这里是修改之前:

public class CatSorter : Comparer<Achat>
{
    public override int Compare(Achat x, Achat y)
    {
        int result = x.CatArt.CompareTo(y.CatArt);

        if (result != 0)
        {
            return result;
        }
        else
        {
            result = x.CatOrder.CompareTo(y.CatOrder);

            if (result != 0)
            {
                return result;
            }
            else
            {
                return x.NomArt.CompareTo(y.NomArt);
            }
        }
    }
}

修改后:

public class CatSorter : Comparer<Achat>
{
    public override int Compare(Achat x, Achat y)
    {
        int result = x.CatOrder.CompareTo(y.CatOrder);

        if (result != 0)
        {
            return result;
        }
        else
        {
            result = x.CatArt.CompareTo(y.CatArt);

            if (result != 0)
            {
                return result;
            }
            else
            {
                return x.NomArt.CompareTo(y.NomArt);
            }
        }
    }
}

在读取和分组Listview的方法中,有必要按文章名称(CatArt)而不是排名编号(CatOrder)对列表进行分组。 这是要纠正的行:

_groupingCollection.ArrangeItems(new CatSorter(), (x => x.CatArt));

完成这些修改后,程序会按类别对文章进行分组,并根据用户选择的顺序对类别进行分类,最重要的是,类别的名称显示为组的标题,而不是排名号。 我希望我的答案很清楚。