Click here to Skip to main content
15,887,135 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
Hi guys

Here we have listORG with 3 fields:

Idx   ,   Etude   ,   Name
----------------------------------
1         Etude1      John
2         Etude2      John
3         Etude3      John
4         Etude4      John
5         Etude5      Merry
6         Etude6      Merry
7         Etude7      John
8         Etude8      John
9         Etude9      Merry


Here we have listHowMany :

Idx   ,   Name   ,   HowManyEtudes
----------------------------------------------
1         John       6
2         Merry      2



So if you see, the socond list shows how many etudes are for the persons John and Merry.

So I want to programming this by Observable Collection. Because I want any update on any of these lists, updates the other one. Like add new, or delete, or edit.

Would you please help me on this?

What I have tried:

Actually I tried some codes from internet, but no luck.
Posted
Updated 17-Mar-24 23:15pm
v2
Comments
CHill60 12-Mar-24 5:14am    
Then share what you tried and explain what "no luck" means to you. We are more than willing to help people who are stuck but we are not just going to do your assignment for you.
Sh.H. 12-Mar-24 5:29am    
@CHill60
I just copied some codes from internet. They did not work as what I want. So I do not think they would be good as reference to copy here.

There are problems here with what you want to do: you can't use a single ObservableCollection for two different lists, and while you could put all the items from both into a weakly typed ObservableCollection and cast them appropriately when you access it, it's not the same as having separate collections and would make your code much more complicated and hard to read / maintain.

You could use two ObservableCollections, and that would work reasonably well - but even then, that only raises event when the collection is changed by and Add, Remove, or reordering operation. You will not get an event when an item in the collection has it's members changed: myObservableCollection(0).Name = "New name" will not generate an event.
 
Share this answer
 
Comments
Graeme_Grant 12-Mar-24 7:17am    
It can be done. See my answer below. ;)
You would use a CollectionViewSource and use grouping. I assume that you are using WPF. Here is a sample: How to: Sort and Group Data Using a View in XAML - WPF .NET Framework | Microsoft Learn[^].

Hereare some more things that you can do with the CollectionViewSource: CollectionViewSource | 2,000 Things You Should Know About WPF[^]

Here is an example using code only: Grouping based on two or more properties[^]

UPDATE

Here is a search with hundreds more examples: wpf CollectionViewSource grouping - Google Search[^]

UPDATE #2

You tend not not try very hard, that is why I pushed you to do your own research and try. That is what being a programmer is all about - learning and solving problems.

Here is what I have used to build a solution to your question: GroupStyle | 2,000 Things You Should Know About WPF[^]. In this code sample, it shows you how to group items in a ListBox control - The Group Name and the Items within that group.

For your requirement, you do not require the Items collection, just the Count. The CollectionViewSource Class[^] has a CollectionViewSource.Source Property[^]. In Xaml, this is the Items collection.

Now for a sample app:
1. Create a new WPF project named: WpfCollectionViewSourceGrouping
2. Add a People class
C#
namespace WpfCollectionViewSourceGrouping;

public class Person
{
    public string Name { get; set; }

    public string Country { get; set; }
}

3. Generate sample data in the MainWindow.cs class:
C#
using System.Collections.ObjectModel;

namespace WpfCollectionViewSourceGrouping;

public partial class MainWindow
{
    public ObservableCollection<Person> People { get; set; } = new();

    private static List<string> countries = new()
    {
        "Australia",
        "Canada",
        "United Kingdom",
        "United States"
    };

    public MainWindow()
    {
        InitializeComponent();

        Random rand = new();
        
        for (int i = 0; i < 20; i++)
        {
            People.Add(new(){ Name = $"Person {i}", Country = countries[rand.Next(0, countries.Count)]});
        }

        DataContext = this;
    }
}

4. Now we can create our window / data views:
XML
<Window x:Class="WpfCollectionViewSourceGrouping.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">

    <Grid>
        <Grid.Resources>
            <CollectionViewSource x:Key="GroupedView" Source="{Binding People}">
                <CollectionViewSource.SortDescriptions>
                    <scm:SortDescription PropertyName="Country" />
                    <scm:SortDescription PropertyName="Name" />
                </CollectionViewSource.SortDescriptions>
                <CollectionViewSource.GroupDescriptions>
                    <PropertyGroupDescription PropertyName="Country" />
                </CollectionViewSource.GroupDescriptions>
            </CollectionViewSource>
        </Grid.Resources>

        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>

        <ListBox ItemsSource="{Binding People}"
                 HorizontalContentAlignment="Stretch">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition />
                            <ColumnDefinition />
                        </Grid.ColumnDefinitions>
                        <TextBlock Text ="{Binding Name}" />
                        <TextBlock Text ="{Binding Country}" Grid.Column="1"/>
                    </Grid>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>

        <ListBox ItemsSource="{Binding Source={StaticResource GroupedView}}"
                 HorizontalContentAlignment="Stretch" Grid.Column="1">
            <ListBox.GroupStyle>
                <GroupStyle>
                    <GroupStyle.ContainerStyle>
                        <Style TargetType="{x:Type GroupItem}">
                            <Setter Property="Template">
                                <Setter.Value>
                                    <ControlTemplate>
                                        <Grid>
                                            <Grid.ColumnDefinitions>
                                                <ColumnDefinition />
                                                <ColumnDefinition />
                                            </Grid.ColumnDefinitions>
                                            <TextBlock Text ="{Binding Name}" />
                                            <TextBlock Text ="{Binding Items.Count}" Grid.Column="1"/>
                                        </Grid>
                                    </ControlTemplate>
                                </Setter.Value>
                            </Setter>
                        </Style>
                    </GroupStyle.ContainerStyle>
                </GroupStyle>
            </ListBox.GroupStyle>
        </ListBox>

    </Grid>
</Window>

5. Run the app and you should now see the following: Sample app screenshot[^]

Doing your research using Google Search will yield results. Unless you're on the cutting edge with very new tech, others have encountered similar problems. WPF is over 17 years old, so you are not Robinson Crusoe!

As shown above, you may not find the exact solution that you are looking for however understanding what the code does enables you to find a working solution. This is called programming.

Enjoy!
 
Share this answer
 
v5
Comments
Pete O'Hanlon 12-Mar-24 7:52am    
I was just coming here to answer this very thing. I'll not bother now because this you answered this with a version of the answer I would have given. A 5 from me.
Graeme_Grant 12-Mar-24 7:58am    
Thank you! :)
Sh.H. 13-Mar-24 2:41am    
@Graeme_Grant
Thanks Graeme for the answer.
I read I posts for hours.
But there are some problems I need to better understand.
1 - As I understood, CollectionViewSoure will group items, not count them. So follow my question, how can I find out that how many "John" are in my list?
2 - After grouping, how can I bind it to new DataGrid? Which when user edit it, the source data get change?

With respect, may I ask you to do me favor and kindly please make a simple code? It will fully help me to learn and understand better on it. Thank you very much.
Graeme_Grant 13-Mar-24 4:31am    
The CollectionViewSource is a custom view of the collection. You can have as many as you want.

1. Use the Count for the quantity, like you would with any other collection.
2. The links provide examples of how to use them. If I provided the code, it would be the same as in the examples in the links.
Sh.H. 13-Mar-24 5:19am    
@Graeme_Grant
Dear Graeme. I already used Observable Collection in my code. So have I change this to Collection? Or I should make a new list as collection?
You don't need an ObservableCollection to "count"; but you can substitute if you want.
public class Org {
   public int Idx;
   public string Etude;
   public string Name;
}

static List<Org> _listOrg = new List<Org>();
static Func<string, int> _countEtudes = ( s ) => _listOrg.Count( x => x.Name.Equals( s ) );

public class HowMany {
   public int Idx;
   public string Name;
   public int HowManyEtudes => _countEtudes( this.Name );
}


(If you don't use statics, you need to "D.I." (dependency inject) the Org list).
 
Share this answer
 
Comments
Graeme_Grant 17-Mar-24 4:20am    
He has a WPF app, so needs a WPF solution. A CollectionViewSource will do what he wants. Check his Question history 😉
Sh.H. 17-Mar-24 5:39am    
@Graeme_Grant
Dear friend.
I tried a lot research on web during these days.
I could not find a working solution.
May I ask you kindly do me favor an write a sample code ?
I really need your kindness on this.
Thank you.
Graeme_Grant 17-Mar-24 6:32am    
I replied to your post in our thread.
Sh.H. 17-Mar-24 6:37am    
@Graeme_Grant
Yes you just gave a link to read about CollectionViewSource.
But I could not find a way to program.
Graeme_Grant 17-Mar-24 6:40am    
please respond in the other thread as this conversation is not related to Gerry's solution.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900