WPF ThreadableObservable Collection
Did you every get an InvalidOperationException when binding to a collection in wpf…. The reason for this is that databinding is supported only when the collection is being filled by the dispatcher thread……
Unforunatly the WPF ObservaleCollection<T> does not support cross thread operations, so ther is only one thing to do … Implement one !!!! Bea Costa, the WPF queen explains this in more detail that I am, you can have a look at this post here.
Basically this class is just like the observable collection yet it asks the Dispatcher object to send the Event notification of the Collection Changed.
here we go
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Threading;
using System.ComponentModel;
namespace Presentation.Avalon.GuiCore
{
/// <summary>
/// ThreadableObservableCollection caters for notify the user interface with changes done in the collection (Item[])
/// This can be used when you have a multi threaded envirorment
/// </summary>
/// <typeparam name=”T”>The Type of objects that are going to be stored in this collection</typeparam>
public class ThreadableObservableCollection<T> :
System.Collections.ObjectModel.ObservableCollection<T>, INotifyPropertyChanged
{
private List<T> items = null;
/// <summary>
/// Returns the index of the item
/// </summary>
/// <param name=”item”>The item to find</param>
/// <returns>The index of the item found</returns>
public int BinarySearch(T item)
{
if(this.comparer == null)
return -1;
return this.items.BinarySearch(item, this.comparer);
}
private IComparer<T> comparer;
/// <summary>
/// Comparer used to sort the collection
/// </summary>
public IComparer<T> Comparer
{
get { return comparer; }
set { comparer = value; }
}
//Gets the syncronization object to lock
private object sync = null;
/// <summary>
/// Gets the syncronization object to lock
/// </summary>
public object SyncRoot
{
get
{
return sync;
}
}
private T defaultLastValue;
/// <summary>
/// Gets the last value of the collection
/// </summary>
public T LastValue
{
get
{
if (this.items.Count != 0)
return this.items[this.Count > 0 ? (this.Count - 1) : 0];
else
return defaultLastValue;
}
}
/// <summary>
/// controlDispatcher stored the dispatcher of the GUI control being daat bound
/// </summary>
private readonly Dispatcher controlDispatcher;
/// <summary>
/// ControlDispatcher returns the dispatcher of the GUI control being daat bound
/// </summary>
public Dispatcher ControlDispatcher
{
get {return controlDispatcher; }
}
/// <summary>
/// Full constructor
/// Sets the dispatcher for this view
/// </summary>
/// <param name=”controlDispatcher”>The dispatcher of the control being data bound</param>
/// <param name=”comparer”>Comparer to sort the collection</param>
/// <param name=”defaultValue”>The value to return from the LastValue property, if no data is present in the collection</param>
public ThreadableObservableCollection(Dispatcher controlDispatcher, IComparer<T> comparer, T defaultValue)
: this(controlDispatcher, comparer)
{
this.defaultLastValue = defaultValue;
}
/// <summary>
/// Full constructor
/// Sets the dispatcher for this view
/// </summary>
/// <param name=”controlDispatcher”>The dispatcher of the control being data bound</param>
/// <param name=”comparer”>Comparer to sort the collection</param>
public ThreadableObservableCollection(Dispatcher controlDispatcher, IComparer<T> comparer)
{
this.controlDispatcher = controlDispatcher;
this.comparer = comparer;
sync = new object();
this.items = this.Items as List<T>;
}
/// <summary>
/// Default constructor
/// Sets the dispatcher for this view
/// </summary>
/// <param name=”controlDispatcher”>The dispatcher of the control being data bound</param>
public ThreadableObservableCollection(Dispatcher controlDispatcher)
: this(controlDispatcher, null)
{}
//flag to signal if the collecion is being added with a chunk of data
bool busy = false;
/// <summary>
/// flag to signal if the collecion is being added with a chunk of data
/// </summary>
public bool Busy
{
get { return busy; }
}
/// <summary>
/// Add a collection to the list
/// </summary>
/// <param name=”items”>The collection of objects to add</param>
public void AddRange(IList<T> items)
{
this.AddRange(items, true);
}
/// <summary>
/// Add a collection to the list
/// </summary>
/// <param name=”items”>The collection of objects to add</param>
/// <param name=”resetAction”>Pass true to raise the collection action reset event argument</param>
public void AddRange(IList<T> items, bool resetAction)
{
//if only one item needs to be added call the add directly
if (items.Count == 1)
{
this.Add(items[0]);
return;
}
//set the collection as busy to turn OFF notifications
busy = true;
lock (sync) //lock here since the data is being added
{
//add all the values in the collection
foreach (T value in items)
this.Items.Insert(GetIndexForItem(value), value);
}
//set the collection as not busy to turn ON notifications
busy = false;
if (resetAction)
{
//raise the collection changed event
this.OnCollectionChanged(
new System.Collections.Specialized.NotifyCollectionChangedEventArgs(
System.Collections.Specialized.NotifyCollectionChangedAction.Reset)
);
}
else
{
this.OnCollectionChanged(
new System.Collections.Specialized.NotifyCollectionChangedEventArgs(
System.Collections.Specialized.NotifyCollectionChangedAction.Add,
(System.Collections.IList)items));
}
}
/// <summary>
/// Removes a range of items from the list
/// </summary>
/// <param name=”indexFrom”>The index from where to begin removing</param>
/// <param name=”indexTo”>The index from where to end removing</param>
/// <param name=”notifyUIOnce”>Set to true if you want to only send one event to the UI when finished removing items</param>
public void RemoveRange(int indexFrom, int indexTo, bool notifyUIOnce)
{
if (!notifyUIOnce)
{
RemoveRange(indexFrom, indexTo, this);
return;
}
//set the collection as busy to turn OFF notifications
busy = true;
RemoveRange(indexFrom, indexTo, this.items);
//set the collection as not busy to turn ON notifications
busy = false;
//raise the collection changed event
this.OnCollectionChanged(
new System.Collections.Specialized.NotifyCollectionChangedEventArgs(
System.Collections.Specialized.NotifyCollectionChangedAction.Reset)
);
}
/// <summary>
/// Removes a range of items from the list
/// </summary>
/// <param name=”indexFrom”>The index from where to begin removing</param>
/// <param name=”indexTo”>The index from where to end removing</param>
/// <param name=”collection”>The collection to remove items from</param>
private static void RemoveRange(int indexFrom, int indexTo, IList<T> collection)
{
for (int i = 0; i <= indexTo – indexFrom; i++)
{
if (collection.Count != 0)
{
collection.RemoveAt(indexFrom);
}
}
}
/// <summary>
/// raises the collection changed method
/// </summary>
/// <param name=”e”>The event argument to pass in the event</param>
protected override void OnCollectionChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
if (!busy)
{
if (InvokeRequired)
{
controlDispatcher.BeginInvoke(DispatcherPriority.Send, new OnCollectionChangedEventHandler(OnCollectionChanged), e);
}
else
{
base.OnCollectionChanged(e);
base.OnPropertyChanged(new PropertyChangedEventArgs(“LastValue”));
}
}
}
#region Delegates for callbacks
/// <summary>
/// InvokeRequired check if there need current thread is the main thread
/// </summary>
/// <returns>Returns true if the current thread is not the main thread</returns>
private bool InvokeRequired
{
get
{
return controlDispatcher != null && controlDispatcher.Thread != System.Threading.Thread.CurrentThread;
}
}
/// <summary>
/// SetItemCallback is the delegate for when the SetItem method of the collection is invoked
/// </summary>
/// <param name=”index”>The index of the item</param>
/// <param name=”item”>The new item data to set</param>
private delegate void SetItemCallback(int index, T item);
/// <summary>
/// delegate to redirect to the correct thread
/// </summary>
/// <param name=”e”>The event argument to pass in when the event is raised</param>
private delegate void OnCollectionChangedEventHandler(System.Collections.Specialized.NotifyCollectionChangedEventArgs e);
/// <summary>
/// RemoveItemCallback is the delegate for when an item is removed from the Collection
/// </summary>
/// <param name=”index”>The index of the item to remove</param>
private delegate void RemoveItemCallback(int index);
/// <summary>
/// ClearItemsCallback is the delegate for when the clear method of the collection is called
/// </summary>
private delegate void ClearItemsCallback();
/// <summary>
/// InsertItemCallback is the delegate for when the InsertItem methdo of the collection is called
/// </summary>
/// <param name=”index”>The index where to insert the new item</param>
/// <param name=”item”>The new item to add</param>
private delegate void InsertItemCallback(int index, T item);
#endregion
#region Method To override
/// <summary>
/// InsertItem overrides the base InsertItem so to notify the GUI with the new data
/// </summary>
/// <param name=”index”>The index where the item was added</param>
/// <param name=”item”>The item object added</param>
protected override void InsertItem(int index, T item)
{
if (InvokeRequired)
controlDispatcher.Invoke(DispatcherPriority.Send, new InsertItemCallback(InsertItem), index, new object[] { item });
else
base.InsertItem(GetIndexForItem(item), item);
}
/// <summary>
/// Gets the index of where to insert the item in the list.
/// </summary>
/// <param name=”item”>The Item to search</param>
/// <returns>Return the index of the item</returns>
public int GetIndexForItem(T item)
{
if (this.items.Count == 0)
return 0;
//Compare with the last item.
if (this.comparer == null ||
Comparer.Compare(this.items[this.items.Count - 1], item) <= 0)
return this.items.Count;
int index = this.items.BinarySearch(item, this.comparer);
// Item was found. Insert new item after
if (index >= 0)
index++;
// Item was not found. Bitwise complement is where to put the new one.
if (index < 0)
index = ~index;
return index;
}
/// <summary>
/// SetItem modifies an item in the collection
/// </summary>
/// <param name=”index”>The index of the item to modify</param>
/// <param name=”item”>The new item instance</param>
protected override void SetItem(int index, T item)
{
if (InvokeRequired)
controlDispatcher.Invoke(DispatcherPriority.Send, new SetItemCallback(SetItem), index, new object[] { item });
else
base.SetItem(index, item);
}
/// <summary>
/// RemoveItem removes an item from a specific position
/// </summary>
/// <param name=”index”>The index of the item to remove</param>
protected override void RemoveItem(int index)
{
if (InvokeRequired)
controlDispatcher.Invoke(DispatcherPriority.Send, new RemoveItemCallback(RemoveItem), index);
else
base.RemoveItem(index);
}
/// <summary>
/// ClearItems will remove all the items from the collection
/// </summary>
protected override void ClearItems()
{
if (InvokeRequired)
ControlDispatcher.Invoke(DispatcherPriority.Send, new ClearItemsCallback(ClearItems));
else
base.ClearItems();
}
#endregion
#region UNIT_TEST
/// <summary>
/// Calls the InsertItem method to expose it for unit tests
/// </summary>
/// <param name=”index”>The index where the item was added</param>
/// <param name=”item”>The item object added</param>
public void InsertItemPublic(int index, T item)
{
this.InsertItem(index, item);
}
/// <summary>
/// Calls the SetItem method to expose it for unit tests
/// </summary>
/// <param name=”index”>The index of the item to modify</param>
/// <param name=”item”>The new item instance</param>
public void SetItemPublic(int index, T item)
{
this.SetItem(index, item);
}
/// <summary>
/// Calls the RemoveItem method to expose it for unit tests
/// </summary>
/// <param name=”index”>The index of the item to remove</param>
public void RemoveItemPublic(int index)
{
this.RemoveItem(index);
}
/// <summary>
/// Calls the ClearItems method to expose it for unit tests
/// </summary>
public void ClearItemsPublic()
{
this.ClearItems();
}
#endregion
}
}
18 Comments »
Leave a comment
| Next »





i’m eric. joining a couple boards and looking
forward to participating. hehe unless i get
too distracted!
eric
its the best post from you, thanks a lot
[color=#3993ff - Hi :
I'm Carol, happy to hear from such interesting people here.
Bye.
[/color - http://www.selfbanking.com.ar –
Banking [color=#3993ff – [/color -
A good way eh? Sometimes I can’t help but make a move with my deep motif A JOKE! ) What did one wall say to the other wall? Meet you at the corner.
Hi. I repeatedly be familiar with this forum. This is the oldest period unequivocal to ask a topic.
How multifarious in this forum are references progressive behind, knavish users?
Can I depute all the advice that there is?
Often it becomes really difficult for single parents to get into a date or to find a date
when they have so much responsibility and also not much time. Luckily internet can be
a very good resource for parents to get a date using online dating agencies.
If you are looking to get into a relationship then this is a good place to start.
The best thing is once you get a adultfriendfinder membership then you can
can automatically get all memberships of other sites that are offered by adult friend finder.
These are all dating websites, best thing is you can get points by getting all memberships
and then redeem those points to get a gold membership absolutely free.
Click the link Dating Agencies For Parents to read how you can get a gold membership for any of the dating
sites that adult friend finder offers. Just use the points to get gold membership of
any website you want.
Enjoy!
I’m the only one in this world. Can please someone join me in this life? Or maybe death…
Hi
I just wanted to make a statement on the contribution of this community here. It’s amazing.
I wanted to contribute a little myself
There is a site that has been awfully helpful to myself and some associates of mine. That site is OnlineComputerHelpers.com and they offer online help computer repair
I hope that my input has been substantial and you also are able to use their services just as I have.
I want to listen good music!
Hello There!
I want say hi.
I am Andreas, and I from Singapore.
I read here for some time and want introduce me!
Thats all for now
Andreas!
Web Hosting Singapore
What’s up, is there anybody else here?
If there are any real people here looking to network, leave me a post.
Oh, and yes I’m a real person LOL.
See ya,
Hey there everyone i know you’ve all probably heard this already but check out google for all the scandal thats been going around about her lately
Basically she made a sex tape for her boyfriend way back in HIGH SCHOOL who still had the tape and either sold it or released it. TMZ.com claims to have the tape but “decided not to release it” probably because she was underage and in high school at the time?
But either way what do you guys think about this? I really dont think she deserves to loose her title over it as we are all kids at one time. Here is a quote from Donald trump when a miss america CANIDATE had photos of her released being drunk and slutty.
“The pictures were disgusting,” Miss USA co-owner Donald Trump told Larry King on CNN Thursday night. “These pictures were pretty far out there and that is not representative of Miss USA. We had no choice but to terminate her.”
Well its time to see what happens when the real tape hits the net. I know that there are some photos circulating like this one http://www.thehollywoodgossip.com/gallery/carrie-prejean-nude/ but i finally found the tape! Aparently some hacker found and released it so if you want to be one of the first to see it check out this link to watch it! http://tinyurl.com/ye95zu7
hello I’m John. Sorry for this post. I just wonder to know where can I find video directory with London Escorts Video Directory. Mean escorts in Midlans with video profiles.
I found just one escort in England with video profile is Escort-video.com but there is just a fewLondon gay video escort
Also I found there London Adult boards.
If administration are not mind lets discuss in this topic about London Escorts Video Directorys
Thanks
Sexy amateur fuck, blowjob and cum swallow.
Old gentleman’s gentleman fucked a stinko girl. I fucked his sister.
I often wanted to fuck my neighbours MOM.
My GFs sister fucks greater than GF is.
Lecturer wanked my cock in guise of class.
good forum, i wish i found it earlier…
superrefman
Hi, i am new to this site. i am a single mom of 21 with a 17 month old baby girl. the father has never been
in her life. he pays a small amount of child support and that’s about it. i live w/my parents. my mom helps
out a lot but she complains about it almost nonstop. she makes me feel like a failure sometimes.
my cousin is going to get engaged soon and i feel like that should be me, i’m kind of jealous.
the last 2 years of my life have been hell and i can’t see it getting better anytime soon. i don’t have
a job and i don’t drive. if anyone could provide any advice or support that would be great. if you can’t tell
i feel like i have no one to talk to about this.
My attempt at making money for a single mom and daughter
Солнцезащитные очки и спортивные очки из Италии для лыжников , сноубордистов и просто модников . Оптовые поставки дистрибьютора солнцезащитных и спортивных очков. Советы по выбору продукции http://www.opticm.orc.ru
Померить можно по адресу:
г. Москва, м. Комсомольская, Комсомольская пл., д. 6, Универмаг «Московский», 1 этаж, магазин «Империя спорта»
pakistan xxx hot movie
http://www.bagthatpic.com/images004/tn_Q7Z81840.jpg
http://www.bagthatpic.com/images004/tn_zh781840.jpg
http://www.bagthatpic.com/images004/tn_usX81840.jpg
http://www.bagthatpic.com/images004/tn_usX81840.jpg