WPF binding with no duplicates
I have a collection of objects that look like this:
List<MyObject> objects = new List<MyObject>();
objects.Add(new MyObject("Stapler", "Office"));
objects.Add(new MyObject("Pen", "Office"));
objects.Add(new MyObject("Mouse", "Computer"));
objects.Add(new MyObject("Keyboard", "Computer"));
objects.Add(new MyObject("CPU", "Computer"));
class MyObject{
public string name;
public string category;
public MyObject(string n, stri开发者_高级运维ng c){
name=n;
category=c;
}
}
Can I bind that collection to a List in WPF, and have it display the categories of the objects (without duplicates)? (maybe along with the count of objects that's in that category)
For example, i would like the list to show only two items, "Office" and "Computer"
Use a CollectionViewSource
with a PropertyGroupDescription
.
In your Resources
, add the following:
<Window.Resources>
<CollectionViewSource x:Key="MyCollectionViewSource" Source="{Binding Path=CollectionPropertyOnViewModel}">
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="Category"/>
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
</Window.Resources>
Then, for your ItemsControl
, set the ItemsSource
to {Binding Source={StaticResource MyCollectionViewSource}}
.
To style the header template, set the ItemsControl.GroupStyle
property. Also create a DataTemplate
for the items.
Read an excellent blog post from Bea Stollnitz here.
You could do this with LINQ, e.g.:
public class AggregateCount
{
public string Name { get; private set; }
public int Count { get; private set; }
public AggregateCount(string name, int count)
{
this.Name = name;
this.Count = count;
}
}
var aggregateCounts = objects.GroupBy(o => o.category).Select(g => new AggregateCount(g.Key, g.Count()));
ObservableCollection<AggregateCount> categoryCounts = new ObservableCollection<AggregateCount>(aggregateCounts);
You can do whatever yuo want, that is the beauty of WPF.
Make a query to recover what you want in format you want in ModelView layer and bind the result to View. Try to make most complicated stuff of yuor programm on Model layer and leave "dummy" stuff to final binding, as much as it possible obviously, cause the Model and ModelView stuff will be easier to debug and fix errors in the future.
Hope this helps.
I would use Linq :
List<MyObject> distinctObj = (from o in objects select o).Distinct().ToList();
If you dont want to use Linq:
private List<MyObject> objects = new List<MyObject>();
public ObservableCollection<String> Groups
{
get
{
ObservableCollection<String> temp = new ObservableCollection<String>();
foreach (MyObject mo in objects)
{
if (!temp.Contains(mo.category))
temp.Add(mo.category)
}
return temp;
}
set
{
objects = value;
RaisePropertyChanged("Groups");
}
}
精彩评论