I am working on a WPF application that uses UniformGrid
as a container for a number of custom controls (up to 48).
<ItemsControl
ItemsSource="{Binding WellsCollection, IsAsync=True}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="4" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type controls:WellViewModel}">
<controls:WellView/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
In my VM WellsCollection
is an ObservableCollection<WellViewModel>
and WellView
is a child of System.Windows.Controls.Control
.
Removing an item from WellsCollection
causes all the existing controls to be re-created. For instance, if I have 48 WellView
controls contained in UniformGrid
removing one WellViewModel
from WellsCollection
will cause 47 new WellView
controls to be constructed.
I put a breakpoint in WellView
constructor and got this stack trace:
WellAnalysis.dll!WellAnalysis.Controls.WellView.WellView() Line 11 C#
System.Private.CoreLib.dll!System.RuntimeType.CreateInstanceImpl(System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder binder, object[] args, System.Globalization.CultureInfo culture) Unknown
System.Xaml.dll!System.Xaml.Schema.XamlTypeInvoker.CreateInstance(object[] arguments) Unknown
System.Xaml.dll!MS.Internal.Xaml.Runtime.ClrObjectRuntime.CreateInstance(System.Xaml.XamlType xamlType, object[] args) Unknown
System.Xaml.dll!MS.Internal.Xaml.Runtime.PartialTrustTolerantRuntime.CreateInstance(System.Xaml.XamlType xamlType, object[] args) Unknown
System.Xaml.dll!System.Xaml.XamlObjectWriter.Logic_CreateAndAssignToParentStart(MS.Internal.Xaml.Context.ObjectWriterContext ctx) Unknown
System.Xaml.dll!System.Xaml.XamlObjectWriter.WriteEndObject() Unknown
PresentationFramework.dll!System.Windows.FrameworkTemplate.LoadTemplateXaml(System.Xaml.XamlReader templateReader, System.Xaml.XamlObjectWriter currentWriter) Unknown
PresentationFramework.dll!System.Windows.FrameworkTemplate.LoadOptimizedTemplateContent(System.Windows.DependencyObject container, System.Windows.Markup.IComponentConnector componentConnector, System.Windows.Markup.IStyleConnector styleConnector, System.Collections.Generic.List<System.Windows.DependencyObject> affectedChildren, System.Windows.UncommonField<System.Collections.Hashtable> templatedNonFeChildrenField) Unknown
PresentationFramework.dll!System.Windows.FrameworkTemplate.LoadContent(System.Windows.DependencyObject container, System.Collections.Generic.List<System.Windows.DependencyObject> affectedChildren) Unknown
PresentationFramework.dll!System.Windows.StyleHelper.ApplyTemplateContent(System.Windows.UncommonField<System.Collections.Specialized.HybridDictionary[]> dataField, System.Windows.DependencyObject container, System.Windows.FrameworkElementFactory templateRoot, int lastChildIndex, System.Collections.Specialized.HybridDictionary childIndexFromChildID, System.Windows.FrameworkTemplate frameworkTemplate) Unknown
PresentationFramework.dll!System.Windows.FrameworkElement.ApplyTemplate() Unknown
PresentationFramework.dll!System.Windows.FrameworkElement.MeasureCore(System.Windows.Size availableSize) Unknown
PresentationCore.dll!System.Windows.UIElement.Measure(System.Windows.Size availableSize) Unknown
PresentationFramework.dll!System.Windows.Controls.Primitives.UniformGrid.MeasureOverride(System.Windows.Size constraint) Unknown
Recreating all the controls is noticeable and looks really bad.
Why does UIElement.Measure()
cause the control to be reconstructed? Is there anything I can do to avoid recreating the controls?
Thank you in advance!
I am working on a WPF application that uses UniformGrid
as a container for a number of custom controls (up to 48).
<ItemsControl
ItemsSource="{Binding WellsCollection, IsAsync=True}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="4" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type controls:WellViewModel}">
<controls:WellView/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
In my VM WellsCollection
is an ObservableCollection<WellViewModel>
and WellView
is a child of System.Windows.Controls.Control
.
Removing an item from WellsCollection
causes all the existing controls to be re-created. For instance, if I have 48 WellView
controls contained in UniformGrid
removing one WellViewModel
from WellsCollection
will cause 47 new WellView
controls to be constructed.
I put a breakpoint in WellView
constructor and got this stack trace:
WellAnalysis.dll!WellAnalysis.Controls.WellView.WellView() Line 11 C#
System.Private.CoreLib.dll!System.RuntimeType.CreateInstanceImpl(System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder binder, object[] args, System.Globalization.CultureInfo culture) Unknown
System.Xaml.dll!System.Xaml.Schema.XamlTypeInvoker.CreateInstance(object[] arguments) Unknown
System.Xaml.dll!MS.Internal.Xaml.Runtime.ClrObjectRuntime.CreateInstance(System.Xaml.XamlType xamlType, object[] args) Unknown
System.Xaml.dll!MS.Internal.Xaml.Runtime.PartialTrustTolerantRuntime.CreateInstance(System.Xaml.XamlType xamlType, object[] args) Unknown
System.Xaml.dll!System.Xaml.XamlObjectWriter.Logic_CreateAndAssignToParentStart(MS.Internal.Xaml.Context.ObjectWriterContext ctx) Unknown
System.Xaml.dll!System.Xaml.XamlObjectWriter.WriteEndObject() Unknown
PresentationFramework.dll!System.Windows.FrameworkTemplate.LoadTemplateXaml(System.Xaml.XamlReader templateReader, System.Xaml.XamlObjectWriter currentWriter) Unknown
PresentationFramework.dll!System.Windows.FrameworkTemplate.LoadOptimizedTemplateContent(System.Windows.DependencyObject container, System.Windows.Markup.IComponentConnector componentConnector, System.Windows.Markup.IStyleConnector styleConnector, System.Collections.Generic.List<System.Windows.DependencyObject> affectedChildren, System.Windows.UncommonField<System.Collections.Hashtable> templatedNonFeChildrenField) Unknown
PresentationFramework.dll!System.Windows.FrameworkTemplate.LoadContent(System.Windows.DependencyObject container, System.Collections.Generic.List<System.Windows.DependencyObject> affectedChildren) Unknown
PresentationFramework.dll!System.Windows.StyleHelper.ApplyTemplateContent(System.Windows.UncommonField<System.Collections.Specialized.HybridDictionary[]> dataField, System.Windows.DependencyObject container, System.Windows.FrameworkElementFactory templateRoot, int lastChildIndex, System.Collections.Specialized.HybridDictionary childIndexFromChildID, System.Windows.FrameworkTemplate frameworkTemplate) Unknown
PresentationFramework.dll!System.Windows.FrameworkElement.ApplyTemplate() Unknown
PresentationFramework.dll!System.Windows.FrameworkElement.MeasureCore(System.Windows.Size availableSize) Unknown
PresentationCore.dll!System.Windows.UIElement.Measure(System.Windows.Size availableSize) Unknown
PresentationFramework.dll!System.Windows.Controls.Primitives.UniformGrid.MeasureOverride(System.Windows.Size constraint) Unknown
Recreating all the controls is noticeable and looks really bad.
Why does UIElement.Measure()
cause the control to be reconstructed? Is there anything I can do to avoid recreating the controls?
Thank you in advance!
IsAsync=True
was the source of the problem. Without it controls are not being re-created. I am not sure what's going on behind the scenes though.
The help (https://learn.microsoft.com/en-us/dotnet/api/system.windows.data.binding.isasync?view=windowsdesktop-9.0) says "Use the IsAsync property when the get accessor of your binding source property might take a long time."
IsAsync
was there before. I removed it and it actually no longer recreates all the controls! I still don't understand why though. – Alex Gdalevich Commented Jan 31 at 18:00