Click here to Skip to main content
15,891,708 members
Please Sign up or sign in to vote.
5.00/5 (1 vote)
See more:
Hello everybody,

I have a legacy library containing various classes, one of which has a property of type int[]. This array property may contain up to millions of elements. I wish to visualize this array using WPF and C#. The problem is that if I bind that array to an ItemsControl then I don't get any change notifications. On the other hand, if I wrap into an ObservableCollection then I cannot observe changes to the underlying array (these changes happen because of the library itself, not because of my code).

Can anybody suggest a solution?

Cheers,
George.
Posted
Updated 23-Feb-11 2:33am
v2

You could run a thread that simply watches the array for changes, and then re-bind the array to the control when a change is detected.

Or, you could run an array watcher thread that automatically moves the array into an observable colletion , and let the natural WPF binding mechanism do the rest of the work.

Or, you could somehow link each item in the array to an item in an observable collection, at which point you don't need the array-watching thread at all.
 
Share this answer
 
v2
Comments
Olivier Levrey 23-Feb-11 7:51am    
My 5. Proposed as answer.
George Tryfonas 23-Feb-11 8:29am    
John, thanks, these are good suggestions. However, there is one key fact that I forgot to mention: this array may contain tens of thousands up to millions of elements. However, few of them change at a time. Unfortunately, if I create a worker thread that moves items from the array to an observable collection, it will take quite some time until it's done moving them -- which means that refreshing the UI will be quite slow.

On the other hand, you suggest that I create a thread that "watches" the array. By that I understand that you mean that the thread can determine which elements of the array have changed. Could you please elaborate a bit more? If I could do that then I could wrap the array around a custom collection class and send the approriate collection change notifications (i.e. the Replace action).

If there are no better suggestions than the ones you have given I will have to accept your answer as the best one. Thanks for the effort anyway.
fjdiewornncalwe 23-Feb-11 9:52am    
+5. I like the approach.
I suppose it's pretty safe to assume that you can't know approximately what block of array elements is most likely to change, so...

You could kind of load-balance by divvying up index blocks among several threads. Since the number of elements is variable, I would setup some way to determine how big each array index block is on a per-thread basis, so for example, if you have 5000 elements, you could create 10 threads, and assign a block of 500 elements to each thread. This would make the change detection somewhat faster.

If you have over 50k elements, you could create more threads and/or watch larger blocks per thread.

It would be a challenging task to marshall all of these things, but I would personally get a real kick out of having to come up with a solution, if it were me.

It's too bad you're not using .Net 4, because it supports parallel tasking on a multi-cpu machine, and it's built just for problems like this.

BTW, this load-balancing approach would still require you to wqrap the array in an ObservableCollection of integers, and update those integers from from the array. I would probably build my items like this:

C#
public class ArrayItem : IObservable
{
    private Array[int] m_array = null;
    private int m_value;
 
    public int Value
    {
        get
        {
            return m_value;
        }
        set
        {
            m_value = value;
            OnPropertyChanged("Value");
        }
    }
 
    public int Index { get; set; }
     
    //--------------------------------------------------------------------
    public void OnPropertyChanged(string propertyName)
    {
        // blah blah
    }
 
    //--------------------------------------------------------------------
    public ArrayItem(Array[] int source, int index)
    {
        m_array = source;
        Index   = index;
        Value   = m_array[Index];
    }

 
    //--------------------------------------------------------------------
    // call this method from the thread when the array value changes
    public UpdateValue()
    {
        Value   = m_array[Index];
    }
}


Of course, you could probably avoid passing in the array if it's static and you can get to it anywhere in your app.
 
Share this answer
 
v5
Comments
George Tryfonas 23-Feb-11 13:51pm    
John,

thanks for your complete and excellent answer. I'll find my way from here.

George.

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