wpf - UniformGrid recreates all child controls when one is removed - Stack Overflow

admin2025-04-17  2

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!

Share Improve this question asked Jan 30 at 21:22 Alex GdalevichAlex Gdalevich 7018 silver badges17 bronze badges 3
  • 1 This is not reproducible. Please provide more details about what you are actually doing, especially how exactly you are removing elements from WellsCollection. Also explain why you think that IsAsync=True on the ItemsSource Binding would have any effect. – Clemens Commented Jan 31 at 7:36
  • This is legacy code and 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
  • It seems your current scenario is not "virtualizing". Don't know if UniformGrid can virtualize. It's not a "standard" tool box item. learn.microsoft.com/en-us/dotnet/api/… – Gerry Schmitz Commented Feb 2 at 19:17
Add a comment  | 

1 Answer 1

Reset to default -1

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."

转载请注明原文地址:http://anycun.com/QandA/1744889925a89067.html