Im designing an UWP movie app and i need several ObservableCollections to store different movie lists. I wanna use ObservableCollection[Index], but dont know how to initialize it.
I've tried the following code but failed:
public static ObservableCollection<Subject>[] FullMovieList = new ObservableCollection<Subject>[6];
How can i accomplish it? Thx~
You create array of ObservableCollection<Subject> correctly.
But you create array only, not collection in array itself.
You should create collections also;
for (int a = 0; a < FullMovieList.Length; a++)
{
FullMovieList[a] = new ObservableCollection<Subject>();
}
Building a new collection each time you want to add range of objects is not good rather i would follow below design.
Build a class inheriting from ObservableCollection , so that you can access Items property which is protected and then create a AddRange method which will add items into it
public class MyObObservableCollection<T> : ObservableCollection<T>
{
public void AddRange(IEnumerable<T> items)
{
foreach (var item in items)
{
this.Items.Add(item);
}
}
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add));
}
Related
My UI has a ListBox which is bound to a Collection. Right now this happens to be an ObservableCollection
My objective is to add objects to this Collection via the UI, and have the ListBox dynamically update, all while maintaining a sorted Collection.
I am aware that there is some SortedView that I can use in WPF. But that is not what I want - I need the actual Collection to remain sorted because my business logic requires a sorted collection.
One way that I thought of, is to create my own Collection class which uses a SortedList internally, and implements the INotifyCollectionChanged interface and produces NotifyCollectionChangedEventArgs event when the internal list changes. Sounds like a lot of work!
Is there a simple solution that I've missed?
Depending on your exact needs, the simplest approach is to keep your ObservableCollection, but wrap in in a new property of type ICollectionView:
public class MyViewModel {
private CollectionViewSource _collectionViewSource;
public ICollectionView MyCollectionView => _collectionViewSource.View;
public MyViewModel(ObservableCollection<MyDataItem> dataItems) {
_collectionViewSource = new CollectionViewSource() { Items = dataItems };
//Add sorting here using _collectionViewSource.SortDescriptions.Add(...)
}
You can use the wrapper property to extract a sorted list as needed.
Okay so I ended up inheriting from ObservableCollection, and overriding the Add() method.
This did the trick for me. Now my list is always sorted, and the ObservableCollection is the one that Notifies the UI of changes.
public class MyCollection : ObservableCollection<Int32>
{
public new void Add(Int32 x)
{
base.Add(x);
var oldList = new ObservableCollection<Int32>(this.OrderBy(c=>c));
Clear();
foreach(var i in oldList)
{
base.Add(i);
}
}
}
I'm a beginner with C#, any feedback on the code is appreciated.
Following this Topics Xceed WPF propertyGrid show item for expanded collection, how is it possible with XAML to sort the list by Name when Binding to Classes ?
Everytime I would like to add a new Item it should be immediately sorted. It doesn't work because if I use Classes.orderby(x=>x.name) it breaks all the bindings?
Hello After lot's of time the solution is at the same time and not, but here I gave you all the solution:
1) the getters and setter for your Observablecollection
private TheCollection yourcollection;
public TheCollection Yourcollection{
get{
yourcollection.CollectionChanged -= Your_CollectionChanged;
// use sort-Extension to sort pointprofil
yourcollection.Sort();
// read CollectionChange-Event
yourcollection.CollectionChanged += Your_CollectionChanged;
return yourCollection;
}
}
And your Collection have to inherit from ObservableCollection but at the Same time to get an Extension to sort()
here we go:
static class Extensions
public static void Sort<T>(this ObservableCollection<T> collection) where T : IComparable
{
List<T> sorted = collection.OrderBy(x => x).ToList();
for (int i = 0; i < sorted.Count(); i++)
collection.Move(collection.IndexOf(sorted[i]), i);
}
}
public class YourCollections : ObservableCollection<YourPoints>, ICustomTypeDescriptor, INotifyPropertyChanged
{
}
and YourPoints have to inherit from IComparable
I know that you can set up a ListBox to sort automatically. Is there a way to "catch" the sorting so that when the ListBox swaps the position of two items so that I can do the same reordering on another list box? I want sort one list box by by value but keep those values at the same relative index locations compared to another ListBox somewhere else.
I could write a routine to bubble sort the list so that I could make the changes myself, but it I am wondering if there is a more automated since I will likely have to do this at a few different places in the program.
Unfortunately, the Sorted property does not use the IComparable interface implementation just sorts based on the result of ToString of the items. But instead of setting the Sorted property, you can use a sorted data source (a List<>, for example).
Create a wrapper class for the items in the ListBox and implement the IComparable<T> interface on it. Populate a List<> with these ListBoxItem instances, then call the Sort method on the list. Thus you will able to dispatch the CompareTo calls.
public partial class Form1 : Form
{
private class ListBoxItem<T> : IComparable<ListBoxItem<T>>
where T : IComparable<T>
{
private T item;
internal ListBoxItem(T item)
{
this.item = item;
}
// this makes possible to cast a string to a ListBoxItem<string>, for example
public static implicit operator ListBoxItem<T>(T item)
{
return new ListBoxItem<T>(item);
}
public override string ToString()
{
return item.ToString();
}
public int CompareTo(ListBoxItem<T> other)
{
return item.CompareTo(other.item); // here you can catch the comparison
}
}
public Form1()
{
InitializeComponent();
var items = new List<ListBoxItem<string>> { "Banana", "Apple"};
items.Sort();
listBox1.DataSource = items;
}
In my Windows Phone app I used CollectionViewSource.SortDescriptors to sort my LongListSelectors content. Now I migrated to Windows Runtime app and am using ListView to display my content. (And WinRT doesn't have SortDescriptors.)
Using OrderBy<>() on my ObserveableCollection is not an option, since I add the items dynamically (and this would cause a complete reload of the ListView).
How do I "binary insert" on ObservableCollection (similar to what's possible with List<>) or is there any alternative to CollectionViewSource.
You could use something like this A winRT CollectionView with filtering and sorting
Alternatively you could create a class and override ObservableCollection.InsertItem like this.
public class SortedCollection<T> : ObservableCollection<T> where T : IComparable<T>
{
protected override void InsertItem(int index, T item)
{
int sortedIndex = FindSortedIndex(item);
base.InsertItem(sortedIndex, item);
}
private int FindSortedIndex(T item)
{
//simple sorting algorithm
for (int index = 0; index < this.Count; index++)
{
if (item.CompareTo(this[index]) > 0)
{
return index;
}
}
return 0;
}
}
To use this class create a new collection and add the items.
SortedCollection<int> sortedCollection = new SortedCollection<int>();
sortedCollection.Add(3);
sortedCollection.Add(1);
sortedCollection.Add(5);
sortedCollection.Add(4);
sortedCollection.Add(2);
//the sorted collection will be 1,2,3,4,5
When I add an item to the CheckedListBox list box I also want to store a reference to another object. I tried adding a new instance of this object to the CheckedListBox.
public class CheckedListBoxExtention : CheckedListBox
{
private ReferenceItem _referenceItem;
public ReferenceItem storedItem
{
get { return _referenceItem; }
set { _referenceItem = value; }
}
public CheckedListBoxExtention(ReferenceItem storedItem)
{
_referenceItem = storedItem;
}
}
This works in that later when I foreach though the items in CheckedListBox I have a reference to the _referenceItem object. However, when I add items like this, CheckedListBox shows up as blank (the list in the GUI itself). So I am trying to find a way to override the item text or something like that.
This is the code I used to fix the problem
class ReferenceItemWrapper
{
private ReferenceItem _item;
public ReferenceItemWrapper(ReferenceItem item)
{
_item = item;
}
public ReferenceItem getItem
{get {return _item;}}
public override string ToString()
{
return _item.ToString();
}
}
I am a bit new to wrappers. Why exactly did it work after it was wrapped when it did not work when I added the ReferenceItem directly to the CheckedListBox?
The CheckedListBox uses the ToString method of the objects in the list to populate the captions in the box. Rather than extend the CheckedListBox, just create a wrapper class that lets you store both your reference and a caption, and implements a ToString method which returns your caption. Just create one of your wrapper objects, stick the text in it, stick your reference in it, then add the wrapper object to the list box.