Your Privacy Matters: We use our own and third-party cookies to improve your experience on our website. By continuing to use the website we understand that you accept their use. Cookie Policy
65
xamPivotGrid bound to ObservableCollection<T> - exception if >1 item changes simultaneously
posted

I'm using a xamPivotGrid with a FlatDataSource whose ItemsSource is an observable collection.

When an item in the observable collection changes, the pivot grid updates appropriately.

I have a problem when several items in the collection change at once. In this case, an exception is thrown is thrown from Infragistics.Olap.FlatData.FlatDataModelProvider. The stacktrace is at the end of this post.

I'd really appreciate any ideas how to fix or work around this problem. 

The problem can be reproduced with the following XAML and C# code....

 

XAML

<Window x:Class="WpfPivot.MainWindow"

 

        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

        Title="MainWindow" Height="350" Width="525" xmlns:igDP="http://infragistics.com/DataPresenter" xmlns:ig="http://schemas.infragistics.com/xaml">

    <Grid>

        <Grid.ColumnDefinitions>

            <ColumnDefinition Width="0.7*" />

            <ColumnDefinition Width="0.3*" />

        </Grid.ColumnDefinitions>

        <ig:XamPivotGrid Grid.Column="0" Grid.Row="0" Name="grid" DataSource="{Binding}" />

        <ig:XamPivotDataSelector Grid.Column="1" Grid.Row="0" Name="selector" DataSource="{Binding}" />

    </Grid>

</Window>

 

 

Codebehind

using System;

 

using System.Collections.Generic;

using System.Collections.ObjectModel;

using System.Linq;

using System.Threading;

using System.Windows;

using Infragistics.Olap;

using Infragistics.Olap.FlatData;

 

namespace WpfPivot

{

    public partial class MainWindow : Window

    {

        private readonly Random _rand;

 

        public MainWindow()

        {

            _rand = new Random();

            InitializeComponent();

            Loaded += OnLoaded;

        }

 

        public void OnLoaded(object sender, RoutedEventArgs args)

        {

            var data = GetData();

 

            var flatDataSource = new FlatDataSource

            {

                Cube = DataSourceBase.GenerateInitialCube("cube"), 

                ItemsSource = data,

            };

 

            DataContext = flatDataSource;

 

            PeriodicallyChangeData(data,4);

        }

 

        private void PeriodicallyChangeData(IList<MyPivotItemType> data, int numberToUpdatePerIteration)

        {

            new Thread(() =>

            {

                while (true)

                {

                    Dispatcher.Invoke((Action) (() =>

                    {

                        for (int i = 0; i < numberToUpdatePerIteration; i++)

                        {

                            var item = data[_rand.Next() % data.Count];

 

                            item.Quantity += (decimal) _rand.NextDouble() - .5m;

 

                            data.Remove(item);

                            data.Add(item);

                        }

                    }));

                    Thread.Sleep(1000);

                }

            }).Start();

        }

 

        private IList<MyPivotItemType> GetData()

        {

            var data = (

                from broker in new[] {"Al", "Abe", "Alan", "Ariel", "Adrian", "Anthony", "Anabelle", "Abdullah", "Alexander"}

                from account in new[] {"Bo", "Ben", "Brad", "Bella", "Barney", "Bernard", "Beatrice", "Broderick", "Barrington"}

                from asset in new[] {"lead", "feathers", "dirt", "platinum"}

                select new MyPivotItemType {

                    Broker = broker, 

                    Asset = asset, 

                    Account = account, 

                    Quantity = (decimal) _rand.NextDouble()*100 - 50

                }

            ).ToList();

 

            return new ObservableCollection<MyPivotItemType>(data);

        }

    }

 

    internal class MyPivotItemType

    {

        public string Asset { get; set; }

        public string Broker { get; set; }

        public string Account { get; set; }

        public decimal Quantity { get; set; }

    }

}

 

 

Exception details

System.ArgumentOutOfRangeException

{"Non-negative number required.\r\nParameter name: length"}


   at System.Array.Copy(Array sourceArray, Int32 sourceIndex, Array destinationArray, Int32 destinationIndex, Int32 length, Boolean reliable)

   at Infragistics.Olap.FlatData.DataTableMetadata.Insert(Int32 index, DataRowMetadata rowMetadata)

   at Infragistics.Olap.FlatData.FlatDataModelProvider.UpdateLiveData(IEnumerable`1 liveChangedData)

   at Infragistics.Olap.FlatData.FlatDataModelProvider.UpdateLiveData(Boolean isForced)

   at Infragistics.Olap.FlatData.FlatDataModelProvider.<>c__DisplayClass1f.<OnUpdateHierarchiesData>b__1d(Object e)

   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)

   at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)

   at System.Windows.Threading.DispatcherOperation.InvokeImpl()

   at System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(Object state)

   at System.Threading.ExecutionContext.runTryCode(Object userData)

   at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)

   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)

   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)

   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)

   at System.Windows.Threading.DispatcherOperation.Invoke()

   at System.Windows.Threading.Dispatcher.ProcessQueue()

   at System.Windows.Threading.Dispatcher.WndProcHook(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)

   at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)

   at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)

   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)

   at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)

   at System.Windows.Threading.Dispatcher.InvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)

   at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)

   at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)

   at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)

   at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame)

   at System.Windows.Threading.Dispatcher.Run()

   at System.Windows.Application.RunDispatcher(Object ignore)

   at System.Windows.Application.RunInternal(Window window)

   at System.Windows.Application.Run(Window window)

   at System.Windows.Application.Run()

   at WpfPivot.App.Main() in D:\projects\scratch\WpfPivotSimpler\WpfPivot\obj\x86\Debug\App.g.cs:line 0

   at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)

   at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)

   at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()

   at System.Threading.ThreadHelper.ThreadStart_Context(Object state)

   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)

   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)

   at System.Threading.ThreadHelper.ThreadStart()

 

Parents
  • 138253
    Offline posted

    Hello,

    Thank you for your post. I have been looking into it and the code you have provided and  I created a sample project using it and modified it, so now the exception doesn’t occurs. Basically I changed the way the item is added to the DataSource after it has been updated and removed, because since you use a different thread and a dispatcher, more than one item is being updated and the Insert method of the DataTableMetadata class’ Insert method calls the Array’s Insert method which takes as argument length of an array, but the count is less because of the threading and dispatching.

    Hope this helps you.

    XamPivotGridFlatData.zip
Reply Children