I am using the following blog post to bind to the XamDockManager.
http://es.infragistics.com/community/blogs/blagunas/archive/2013/09/24/xamdockmanager-data-binding-contentpanes-with-mvvm.aspx
The context is that the user creates a project from a certain file, they add things to their project, and then they choose to save the project. The project is then saved to disk and reloaded into the ViewModel. This change in ViewModel values is throwing the OnItemsSourcePropertyChanged method off. So I save the project, then set the property that binds to the ItemsSource property to null, then I need to reload the project. The issue comes when I set the ItemsSource to null (I am binding to an ObservableCollection and have tried newing up an ObservableCollection or clearing it, but it does not work either). In the OnItemsSourcePropertyChanged method on the call to AssociatedObject.Items.Clear(), I get the null pointer exception. There are items going into the call, but somewhere in the cleanup something gets messed up. Somewhere deep in the infragistics code that gets called, there is an issue.
Here is the stacktrace:
System.NullReferenceException occurred HResult=-2147467261 Message=Object reference not set to an instance of an object. Source=PresentationFramework StackTrace: at System.Windows.Controls.ItemContainerGenerator.ContainerFromIndex(Int32 index) at Infragistics.Windows.DockManager.TabGroupPane.VerifySelectedItem(Object param) at Infragistics.Windows.DockManager.TabGroupPane.VerifySelectedItem() at Infragistics.Windows.DockManager.TabGroupPane.OnGeneratorStatusChanged(Object sender, EventArgs e) at System.EventHandler.Invoke(Object sender, EventArgs e) at System.Windows.Controls.ItemContainerGenerator.SetStatus(GeneratorStatus value) at System.Windows.Controls.ItemContainerGenerator.Generator.System.IDisposable.Dispose() at Infragistics.Windows.DockManager.DocumentTabPanel.MeasureOverride(Size availableSize) at System.Windows.FrameworkElement.MeasureCore(Size availableSize) at System.Windows.UIElement.Measure(Size availableSize) at System.Windows.ContextLayoutManager.UpdateLayout() at Infragistics.Windows.DataPresenter.DataPresenterBase.OnThemeChanged(DependencyObject target, DependencyPropertyChangedEventArgs e) at System.Windows.PropertyChangedCallback.Invoke(DependencyObject d, DependencyPropertyChangedEventArgs e) at System.Windows.DependencyObject.OnPropertyChanged(DependencyPropertyChangedEventArgs e) at System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e) at Infragistics.Windows.DataPresenter.DataPresenterBase.OnPropertyChanged(DependencyPropertyChangedEventArgs e) at Infragistics.Windows.DataPresenter.XamDataGrid.OnPropertyChanged(DependencyPropertyChangedEventArgs e) at System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args) at System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType) at System.Windows.DependencyObject.InvalidateProperty(DependencyProperty dp, Boolean preserveCurrentValue) at System.Windows.StyleHelper.InvalidatePropertiesOnTemplateNode(DependencyObject container, FrameworkObject child, Int32 childIndex, FrugalStructList`1& childRecordFromChildIndex, Boolean isDetach, FrameworkElementFactory templateRoot) at System.Windows.StyleHelper.ClearTemplateChain(HybridDictionary[] instanceData, FrameworkElement feContainer, FrameworkContentElement fceContainer, List`1 templateChain, FrameworkTemplate oldFrameworkTemplate) at System.Windows.StyleHelper.ClearGeneratedSubTree(HybridDictionary[] instanceData, FrameworkElement feContainer, FrameworkContentElement fceContainer, FrameworkTemplate oldFrameworkTemplate) at System.Windows.StyleHelper.DoTemplateInvalidations(FrameworkElement feContainer, FrameworkTemplate oldFrameworkTemplate) at System.Windows.StyleHelper.UpdateTemplateCache(FrameworkElement fe, FrameworkTemplate oldTemplate, FrameworkTemplate newTemplate, DependencyProperty templateProperty) at System.Windows.Controls.ContentPresenter.OnTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) at System.Windows.DependencyObject.OnPropertyChanged(DependencyPropertyChangedEventArgs e) at System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e) at System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args) at System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType) at System.Windows.DependencyObject.SetValueCommon(DependencyProperty dp, Object value, PropertyMetadata metadata, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType, Boolean isInternal) at System.Windows.DependencyObject.SetValue(DependencyProperty dp, Object value) at System.Windows.Controls.ContentPresenter.OnContentTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) at System.Windows.DependencyObject.OnPropertyChanged(DependencyPropertyChangedEventArgs e) at System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e) at System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args) at System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType) at System.Windows.DependencyObject.InvalidateProperty(DependencyProperty dp, Boolean preserveCurrentValue) at System.Windows.StyleHelper.InvalidatePropertiesOnTemplateNode(DependencyObject container, FrameworkObject child, Int32 childIndex, FrugalStructList`1& childRecordFromChildIndex, Boolean isDetach, FrameworkElementFactory templateRoot) at System.Windows.StyleHelper.ClearTemplateChain(HybridDictionary[] instanceData, FrameworkElement feContainer, FrameworkContentElement fceContainer, List`1 templateChain, FrameworkTemplate oldFrameworkTemplate) at System.Windows.StyleHelper.ClearGeneratedSubTree(HybridDictionary[] instanceData, FrameworkElement feContainer, FrameworkContentElement fceContainer, FrameworkTemplate oldFrameworkTemplate) at System.Windows.StyleHelper.DoTemplateInvalidations(FrameworkElement feContainer, FrameworkTemplate oldFrameworkTemplate) at System.Windows.StyleHelper.UpdateTemplateCache(FrameworkElement fe, FrameworkTemplate oldTemplate, FrameworkTemplate newTemplate, DependencyProperty templateProperty) at System.Windows.Controls.Control.OnTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) at System.Windows.DependencyObject.OnPropertyChanged(DependencyPropertyChangedEventArgs e) at System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e) at System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args) at System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType) at System.Windows.DependencyObject.InvalidateProperty(DependencyProperty dp, Boolean preserveCurrentValue) at System.Windows.StyleHelper.InvalidateContainerDependents(DependencyObject container, FrugalStructList`1& exclusionContainerDependents, FrugalStructList`1& oldContainerDependents, FrugalStructList`1& newContainerDependents) at System.Windows.StyleHelper.DoStyleInvalidations(FrameworkElement fe, FrameworkContentElement fce, Style oldStyle, Style newStyle) at System.Windows.StyleHelper.UpdateStyleCache(FrameworkElement fe, FrameworkContentElement fce, Style oldStyle, Style newStyle, Style& styleCache) at System.Windows.FrameworkElement.OnStyleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) at System.Windows.DependencyObject.OnPropertyChanged(DependencyPropertyChangedEventArgs e) at System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e) at System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args) at System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType) at System.Windows.DependencyObject.InvalidateProperty(DependencyProperty dp, Boolean preserveCurrentValue) at System.Windows.FrameworkElement.UpdateStyleProperty() at System.Windows.TreeWalkHelper.InvalidateOnTreeChange(FrameworkElement fe, FrameworkContentElement fce, DependencyObject parent, Boolean isAddOperation) at System.Windows.FrameworkElement.OnVisualParentChanged(DependencyObject oldParent) at System.Windows.Media.Visual.FireOnVisualParentChanged(DependencyObject oldParent) at System.Windows.Media.Visual.RemoveVisualChild(Visual child) at System.Windows.FrameworkElement.set_TemplateChild(UIElement value) at System.Windows.StyleHelper.DetachGeneratedSubTree(FrameworkElement feContainer, FrameworkContentElement fceContainer) at System.Windows.StyleHelper.DoTemplateInvalidations(FrameworkElement feContainer, FrameworkTemplate oldFrameworkTemplate) at System.Windows.StyleHelper.UpdateTemplateCache(FrameworkElement fe, FrameworkTemplate oldTemplate, FrameworkTemplate newTemplate, DependencyProperty templateProperty) at System.Windows.Controls.ContentPresenter.OnTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) at System.Windows.DependencyObject.OnPropertyChanged(DependencyPropertyChangedEventArgs e) at System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e) at System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args) at System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType) at System.Windows.DependencyObject.SetValueCommon(DependencyProperty dp, Object value, PropertyMetadata metadata, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType, Boolean isInternal) at System.Windows.DependencyObject.SetValue(DependencyProperty dp, Object value) at System.Windows.Controls.ContentPresenter.OnContentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) at System.Windows.DependencyObject.OnPropertyChanged(DependencyPropertyChangedEventArgs e) at System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e) at System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args) at System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType) at System.Windows.DependencyObject.InvalidateProperty(DependencyProperty dp, Boolean preserveCurrentValue) at System.Windows.StyleHelper.InvalidateDependents(Style ownerStyle, FrameworkTemplate frameworkTemplate, DependencyObject container, DependencyProperty dp, FrugalStructList`1& dependents, Boolean invalidateOnlyContainer) at System.Windows.StyleHelper.OnTriggerSourcePropertyInvalidated(Style ownerStyle, FrameworkTemplate frameworkTemplate, DependencyObject container, DependencyProperty dp, DependencyPropertyChangedEventArgs changedArgs, Boolean invalidateOnlyContainer, FrugalStructList`1& triggerSourceRecordFromChildIndex, FrugalMap& propertyTriggersWithActions, Int32 sourceChildIndex) at System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e) at System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args) at System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType) at System.Windows.DependencyObject.SetValueCommon(DependencyProperty dp, Object value, PropertyMetadata metadata, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType, Boolean isInternal) at System.Windows.DependencyObject.SetValue(DependencyPropertyKey key, Object value) at Infragistics.Windows.DockManager.PaneTabItem.OnContentChanged(Object oldContent, Object newContent) at System.Windows.Controls.ContentControl.OnContentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) at System.Windows.DependencyObject.OnPropertyChanged(DependencyPropertyChangedEventArgs e) at System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e) at Infragistics.Windows.Controls.TabItemEx.OnPropertyChanged(DependencyPropertyChangedEventArgs e) at System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args) at System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType) at System.Windows.DependencyObject.SetValueCommon(DependencyProperty dp, Object value, PropertyMetadata metadata, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType, Boolean isInternal) at System.Windows.DependencyObject.SetValue(DependencyProperty dp, Object value) at System.Windows.Controls.HeaderedContentControl.ClearHeaderedContentControl(Object item) at System.Windows.Controls.Primitives.Selector.ClearContainerForItemOverride(DependencyObject element, Object item) at Infragistics.Windows.DockManager.TabGroupPane.ClearContainerForItemOverride(DependencyObject element, Object item) at System.Windows.Controls.ItemsControl.MS.Internal.Controls.IGeneratorHost.ClearContainerForItem(DependencyObject container, Object item) at System.Windows.Controls.ItemContainerGenerator.UnlinkContainerFromItem(DependencyObject container, Object item, IGeneratorHost host) at System.Windows.Controls.ItemContainerGenerator.RemoveAllInternal(Boolean saveRecycleQueue) at System.Windows.Controls.ItemContainerGenerator.OnCollectionChanged(Object sender, NotifyCollectionChangedEventArgs args) at System.Windows.WeakEventManager.ListenerList`1.DeliverEvent(Object sender, EventArgs e, Type managerType) at System.Windows.WeakEventManager.DeliverEventToList(Object sender, EventArgs args, ListenerList list) at System.Windows.WeakEventManager.DeliverEvent(Object sender, EventArgs args) at System.Collections.Specialized.NotifyCollectionChangedEventHandler.Invoke(Object sender, NotifyCollectionChangedEventArgs e) at System.Windows.Data.CollectionView.OnCollectionChanged(NotifyCollectionChangedEventArgs args) at System.Windows.WeakEventManager.ListenerList`1.DeliverEvent(Object sender, EventArgs e, Type managerType) at System.Windows.WeakEventManager.DeliverEventToList(Object sender, EventArgs args, ListenerList list) at System.Windows.WeakEventManager.DeliverEvent(Object sender, EventArgs args) at System.Windows.Data.CollectionView.OnCollectionChanged(NotifyCollectionChangedEventArgs args) at MS.Internal.Controls.InnerItemCollectionView.RefreshOverride() at System.Windows.Data.CollectionView.RefreshInternal() at MS.Internal.Controls.InnerItemCollectionView.Clear() at System.Windows.Controls.ItemCollection.Clear() at SSI.Windows.Simulation.Conjoint.TabGroupPaneItemsSourceBehavior.OnItemsSourcePropertyChanged(IList oldValue, IList newValue) in c:\path\TabGroupPaneItemsSourceBehavior.cs:line 59 InnerException:
Please help! Thanks!
Jon
Hi Jon,
Thank you for your post. I have been looking into your issue and I was wondering whether you could attach a sample application that demonstrates the reported issue. I would like to investigate it because the provided functionality from the above blog is custom.
Looking forward to hearing from you.
I am unable to duplicate the issue with a simple project. Do you mind taking a look at my real project privately?
I'm sure Yanko will respond Monday but I took a quick look and it seems like the problem is the fact that the grid is calling UpdateLayout on itself while the TabGroupPane is releasing the container/element that contains the grid (because the WPF framework is clearing the Theme property). That UpdateLayout call is causing the TabGroupPane to get some notifications and it then asks the ItemContainerGenerator for the element for its selected index and since the base ItemsControl is in the middle of clearing/releasing the item container is results in that exception. One workaround is to not set the Theme property on the grid's defined within a DataTemplate and use a ResourceSetLoader instead.
e.g.
<igWPF:XamDataGrid DataSource="{Binding}"> <igWPF:XamDataGrid.Resources> <igWPF:ResourceSetLoader Locator="{x:Static igWPF:DataPresenterOffice2013.Location}" /> </igWPF:XamDataGrid.Resources></igWPF:XamDataGrid>
Another option would be to create a UserControl and put what you have in the DataTemplate into the UserControl and then just define an instance of the UserControl within the DataTemplate because the problem comes down to the DataTemplate clearing the properties that were set within the DataTemplate when it's being released.
Sorry I'm not familiar with that class (igWPF:ResourceSetLoader). Can you direct me to some documentation on how to use it? Says it requires a x:Key attribute and then still doesn't get applied.
Thanks!
I don't know that there is any documentation specific to that other than just API docs about for the class itself. Did you hit some problem with replacing the declaration of the xamDataGrid within the DataTemplate from what you had to the snippet I pasted in the reply because I tried it in your sample and it worked? ResourceSetLoader is a derived ResourceDictionary so you wouldn't put it within a ResourceDictionary and therefore you wouldn't ever use an x:Key on it. If you're trying to put that into a resource dictionary that you have then you would put it within the MergedDictionaries of your ResourceDictionary. It seems to me like the easiest solution is the second option of creating a UserControl and put the content of the DataTemplate into that. So basically your DataTemplate looks like <DataTemplate><local:UserControl1 /></DataTemplate>
Thank you so much for your help. You made my day!
Who can I thank for needing to do this? You guys, Microsoft, or is it by design?
Thanks,
I'm glad I could help. As to the issue, it's a combination of circumstances but ultimately it is the UpdateLayout call in the DataPresenter that is causing the reentrance that led to this issue. We'll log the issue and look into changing it in the control but at least it shouldn't hold you up.
Just in case others need to do the same thing I did, I ended up following the answer on this page. https://social.msdn.microsoft.com/Forums/vstudio/en-US/f10045d5-3c47-4401-93d4-8ef8b82fa9e5/gridsplitter-drags-out-of-the-window?forum=wpf
I see the problem. Sorry. The first RowDefinition height in the UserControl is set to Auto and not *, so it just takes up as much space as it can.
Thanks. I will look for another solution.
Okay. I was mistaken. It was working when I had this as my structure:
<igWindows:XamTabControl.ContentTemplate> <DataTemplate> <Grid> <Grid.RowDefinitions> <RowDefinition Height="*" MinHeight="44"/> <RowDefinition Height="Auto"/> <RowDefinition Height="*" MinHeight="44"/> </Grid.RowDefinitions>
Then I switched to a XamDockManager like this:
<dockManager:XamDockManager x:Name="_dock" >
<dockManager:DocumentContentHost>
<dockManager:SplitPane> <dockManager:TabGroupPane x:Name="_dynamicTab"> <i:Interaction.Behaviors> <local:TabGroupPaneItemsSourceBehavior ItemsSource="{Binding Scenarios}" HeaderMemberPath="Label" > <local:TabGroupPaneItemsSourceBehavior.ItemTemplate> <DataTemplate> <local:MainTabContentControl /> </DataTemplate> </local:TabGroupPaneItemsSourceBehavior.ItemTemplate> </local:TabGroupPaneItemsSourceBehavior> </i:Interaction.Behaviors> </dockManager:TabGroupPane> </dockManager:SplitPane> </dockManager:DocumentContentHost> </dockManager:XamDockManager>
Then in the MainTabContentControl is the same structure as at the top:
<Grid> <Grid.RowDefinitions> <RowDefinition Height="*" MinHeight="44"/> <RowDefinition Height="Auto"/> <RowDefinition Height="*" MinHeight="44"/> </Grid.RowDefinitions>
I'm still trying to figure out what is different. In a small sample, I cannot reproduce it working under the XamTabControl example, but it does work in my real project. Do you know if there is anything special about XamTabControl content that is different than the DocumentContentHost? I will keep investigating on my real project.
I'm not following how the use of a UserControl would impact this. If you have a RowDefinition whose Height is Auto then it will measure the element in that position within an infinite height so it would go out of view if the element in that position returns a height greater than the available height. That would happen even if you put that outer grid as the Content of a ContentPresenter (which is basically what is happening when it's directly within the DataTemplate). Do you have a sample that shows this problem in the UserControl but the same structure behaving differently when its in the DataTemplate so I could see what is happening?
I have changed my layout to have the UserControl and just noticed I lost some functionality.
Inside my UserControl, I have a Grid -> Grid + GridSplitter + Grid.
In the outer grid's row definitions, the first Grid in the Grid is set to auto with a minheight of 50, the gridsplitter is set to auto, and the last grid row is set to * with minheight 50.
For some reason, the gridsplitter is allowed to go past the bottom of the UserControl container. I understand that I could wrap a scrollviewer around the content and it would let me go down and see the gridsplitter again, but the original functionality I had was that the height of the tabgrouppane content was just filling the space available and not adding the scrollbar.
How does putting content into a usercontrol cause this issue? I have tried setting the verticalalignment and verticalcontentalignment to stretch, but the issue still occurs.
Any ideas? Thanks!