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.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.ThreadHelper.ThreadStart()
Hello,
Thank you for your post. I have been looking into it and it seems like that I am missing something in your scenario, so if this is still an issue for you, could you please send an isolated sample project, where the issue is reproduced, so I can investigate it further for you.
Looking forward for your reply.
I have the exact same problem and I have code posted below. I can't figure out how to do it via your sample so i am posting my code.
Public Class ExecutiveTubeComparisonViewModel Inherits ObservableCollection(Of scll_label) Private Delegate Sub _UpdatePivot(ByVal rec As scll_label) Private Sub UpdatePivot(ByVal rec As scll_label) Me.Add(rec) End Sub Private Sub LoadPivots() Dim LPTask As New Task(Sub() Dim db As New Entities Dim startDate As Date = Date.Parse(Date.Now.Month & "/1/" & Date.Now.Year) Dim daysInCurrentMonth As Integer = Date.DaysInMonth(Date.Now.Year, Date.Now.Month) Dim endDate As Date = Date.Parse(Date.Now.Month & "/" & daysInCurrentMonth & "/" & Date.Now.Year) Dim var = From I In db.scll_label Where I.scll_transactiondate >= startDate And I.scll_transactiondate <= endDate Select I For Each rec In var Try Dim de As Decimal = ((rec.scll_weight - rec.scll_total_tare) / rec.scll_std_weight) * 100 rec.DrawingEfficiency = Decimal.Round(de, 2) Catch ex As Exception rec.DrawingEfficiency = rec.scll_drawlite_factor End Try Application.Current.Dispatcher.Invoke(New _UpdatePivot(AddressOf UpdatePivot), rec) Next End Sub) LPTask.Start() End Sub Public Sub New() LoadPivots() End Sub End Class
Hello Adam,
Thank you for your feedback. I am glad that you resolved your issue and I believe that other community members may benefit from this as well.
Thanks again.
Thanks for your answer - it's helped me a lot.
Adam
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.