Click here to Skip to main content
15,895,192 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
private ObservableCollection<DtSource> _PieChartDB;

        public ObservableCollection<DtSource> PieChartDB
        {
            get
            {
                return _PieChartDB.GroupBy(x => x.Name); 
            }
            set
            {
                if (_PieChartDB != value)
                {
                    _PieChartDB = value;
                    OnPropertyChanged("PieChartDB");

                }
            }
        }

I am getting this error:

Cannot implicitly convert type 'System.Collections.Generic.IEnumerable<System.Linq.IGrouping<string,DataSource1.Model.Entity.DtSource>>' to 'System.Collections.ObjectModel.ObservableCollection<DataSource1.Model.Entity.DtSource>'. An explicit conversion exists (are you missing a cast?)	
Posted
Comments
[no name] 3-Nov-15 4:46am    
I also tried this but its not working :(

var result = _PieChartDB.GroupBy(x => x.Name);
return new ObservableCollection<DtSource>(result);
Andy Lanng 3-Nov-15 6:00am    
As an aside: I's so glad to find someone else who uses RX ^_^
BillWoodruff 3-Nov-15 9:57am    
Please clarify your goal/intention here in response to the solution I posted below. Until we really understand exactly what you want, we are just guessing :)
Maciej Los 3-Nov-15 13:20pm    

The error message tells you directly that the return value of the Property must be the expected Type of the Property. That indicates to me you need another strategy here ... if ...

I assume that your intention is:

1. to implement an Observable Collection of instances of DtSource, where you generate notifications of basic actions on the Collection like: 'Add, 'Remove.

2. at the same time, to maintain an updated data structure in which the DtSource instances are 'Grouped using Linq by the Class 'Name property/key.

The code shown here is based on those two assumptions; if either is incorrect, let me know, and I will remove this post.
C#
// required
using System.Collections.Generic;
using System.Collections.Specialized;

// use in some NameSpace
public class GroupedObservableCollection<T> : List<T>, INotifyCollectionChanged
{
    // ctor
    public GroupedObservableCollection(){}

    private int baseCount = 0;

    public event NotifyCollectionChangedEventHandler CollectionChanged;

    public new void Add(T item)
    {
        base.Add(item);

        if (CollectionChanged != null)
        {
            CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item, base.Count));
        }

        baseCount++;
    }

    public new void Remove(T item)
    {
        if (!base.Contains(item)) return; // throw error ?

        int ndx = base.IndexOf(item);

        Remove(ndx, item);
    }

    public void Remove(int ndx, T item = default(T))
    {
        if (ndx > baseCount) return; // throw error ?

        base.RemoveAt(ndx);

        if (CollectionChanged != null)
        {
            CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item, ndx));
        }

        baseCount--;
    }

    public new void Clear()
    {
        if (baseCount == 0) return; // throw error ?

        base.Clear();

        if (CollectionChanged != null)
        {
            CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
        }

        baseCount = 0;
    }

    public void Move(int ndx1, int ndx2)
    {
        if (ndx1 >= baseCount || ndx2 >= baseCount) return;  // throw error ?

        T temp = base[ndx1];
        base[ndx1] = base[ndx2];
        base[ndx2] = temp;

        if (CollectionChanged != null)
        {
            CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Move, this, ndx1, ndx2));
        }
    }

    public void Replace(int ndx1, T item)
    {
        if (ndx1 >= baseCount) return; // throw error ?

        base[ndx1] = item;

        if (CollectionChanged != null)
        {
            CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, item, base[ndx1]));
        }
    }
}
I made this class Generic, so I could re-use it with different Types of Objects. An outcome of making it generic is that you can't stick a function in it to return the Collection (List) GroupedBy some specific property (Key) of the Type of T (while you might be able to do that using Reflection, I'd say that would be crazy).

So, strategy 2 is to use an instance of this generic class in a way that keeps a GroupedBy collection updated as notifications are generated:
C#
// requires Linq
// in a Form, or other code-context where the Collection is used:

public GroupedObservableCollection<AnyOldClass> test = new GroupedObservableCollection<AnyOldClass>();

// collection in grouped by name form
public IEnumerable<Igrouping><string,>> CollectionCurrentGroups;

// event-handler that is called when the Collection changes:
private void TestOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
    switch (e.Action)
    {
        // set break-points here and verify action is invoked with appropriate parameters in 'e
        // add your code handlers for each type of event here:

        case NotifyCollectionChangedAction.Add:
            UpdateGroupCollection(test);
            break;
        case NotifyCollectionChangedAction.Remove:
            UpdateGroupCollection(test);
            break;
        case NotifyCollectionChangedAction.Move:
            // update not needed here ?
            break;
        case NotifyCollectionChangedAction.Replace:
            UpdateGroupCollection(test);
            break;
        case NotifyCollectionChangedAction.Reset:
            CollectionCurrentGroups = null;
            break;
    }
}

private void UpdateGroupCollection(GroupedObservableCollection<AnyOldClass> collection)
{
    CollectionCurrentGroups = collection.GroupBy(nm => nm.Name);
}

// example of use: in some method, or in a Form Load event, etc.
// set break-points, inspect the value of 'CollectionCurrentGroups
test.CollectionChanged += TestOnCollectionChanged;
test.Add(new AnyOldClass("hello"));
test.Remove(test[0]);
test.Clear();
test.Add(new AnyOldClass("goodbye"));
test.Add(new AnyOldClass("hello again"));
test.Add(new AnyOldClass("goodbye"));
test.Add(new AnyOldClass("hello again"));
test.Move(0,1);
test.Replace(1, new AnyOldClass("what"));
test.Clear();
test.Clear();
Here's the simple Class used for testing here:
C#
public class AnyOldClass
{
    public string Name { set; get; }

    public AnyOldClass(string name)
    {
        Name = name;
    }
}
Caution: as with all code examples you might see here, or on StackOverFlow, etc., it is your responsibility to make sure they work in the context you use them in. Code like this should be regarded as an example for educational purposes only, and used in "production" code only after extensive, careful, testing !
 
Share this answer
 
v4
Comments
Maciej Los 3-Nov-15 13:17pm    
Well explained, Bill!
BillWoodruff 4-Nov-15 2:00am    
Thanks, Maciej !
Neetin_1809 3-Nov-15 13:46pm    
Very Well Explained
BillWoodruff 4-Nov-15 2:01am    
Thanks, Neetin !
Performing the Linq will return a IGrouping<tkey,dtsource> item. This cannot be cast to ObservableCollection<dtsource></dtsource>

If you want aggregates then you will need to select the results from the IGrouping into a DTSource Type before casting as a ObservableCollection<dtsource></dtsource>.
 
Share this answer
 
Comments
BillWoodruff 3-Nov-15 8:11am    
If you show the OP how to cast "the results from the IGrouping into a DTSource Type" to an ObservableCollection ... in a way that "makes sense" in terms of the OP's intention here, you get my five, else you are just repeating the error message :)
Andy Lanng 3-Nov-15 9:04am    
I would have but I had no idea how to interpret the OPs intent.
You seem to have covered all the bases so you can have my 5 instead ^_^
BillWoodruff 3-Nov-15 9:59am    
Thanks, for the up-vote, Andy; I think it's too early yet to make anything but "an intuitive guess" as to what the OP really wants. So, you could be on the "right" track here, and I on the "wrong" one :)
Andy Lanng 3-Nov-15 10:02am    
I'd still 5 for the effort, regardless

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