{"record":{"id":"07a66f35abf39f59","repo":"dotnet/wpf","slug":"sr-cannotrecyleheterogeneoustypes","errorCode":null,"errorMessage":"SR.CannotRecyleHeterogeneousTypes","messagePattern":"SR\\.CannotRecyleHeterogeneousTypes","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/ItemContainerGenerator.cs","lineNumber":333,"sourceCode":"            {\n                DependencyObject container = rblock.ContainerAt(offset);\n\n                UnlinkContainerFromItem(container, rblock.ItemAt(offset));\n                // DataGrid generates non-GroupItem for NewItemPlaceHolder\n                // Dont recycle in this case.\n                bool isNewItemPlaceHolderWhenGrouping = _generatesGroupItems && !(container is GroupItem);\n\n                if (isRecycling && !isNewItemPlaceHolderWhenGrouping)\n                {\n                    Debug.Assert(!_recyclableContainers.Contains(container), \"trying to add a container to the collection twice\");\n\n                    if (_containerType == null)\n                    {\n                        _containerType = container.GetType();\n                    }\n                    else if (_containerType != container.GetType())\n                    {\n                        throw new InvalidOperationException(SR.CannotRecyleHeterogeneousTypes);\n                    }\n\n                    _recyclableContainers.Enqueue(container);\n                }\n\n                if (++offset >= rblock.ContainerCount && rblock != blockR)\n                {\n                    rblock = rblock.Next as RealizedItemBlock;\n                    offset = 0;\n                }\n            }\n\n            // see whether the range hits the edge of a block on either side,\n            // and whether the a`butting block is an unrealized gap\n            bool edgeL = (offsetL == 0);\n            bool edgeR = (offsetR == blockR.ItemCount-1);\n            bool abutL = edgeL && (blockL.Prev is UnrealizedItemBlock);\n            bool abutR = edgeR && (blockR.Next is UnrealizedItemBlock);","sourceCodeStart":315,"sourceCodeEnd":351,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/ItemContainerGenerator.cs#L315-L351","documentation":"When recycling generated containers, ItemContainerGenerator keeps the type of the first recycled container and enqueues only containers of that same type. If a container of a different CLR type is offered for recycling, it throws InvalidOperationException (CannotRecyleHeterogeneousTypes) because recycled containers are pooled by type and mixing types would produce wrong containers on reuse.","triggerScenarios":"Calling Recycle on a range whose realized containers come from different DataTemplates/type overrides (e.g. ListBoxItem vs derived type, or ContentPresenter containers of different types) — common with heterogeneous item templates or ItemContainerStyleSelector.","commonSituations":"Hierarchical or templated lists (TreeView/ItemsControl with DataTemplateSelector) where sibling items resolve to different container types; custom panels recycling across type boundaries.","solutions":["Recycle containers of only one type per generator session; recycle heterogeneous containers individually without mixing them in the same recycle batch.","Return containers of a consistent type from PrepareContainerForItemOverride/SelectTemplate, or disable container recycling (VirtualizationMode.Standard instead of Recycling).","Filter the recycle range to containers of the established _containerType before calling Recycle."],"exampleFix":"// before\nforeach (var c in realizedContainers)\n    generator.Recycle(pos, 1, true); // mixes types -> throws\n\n// after\nType firstType = realizedContainers[0].GetType();\nforeach (var c in realizedContainers.Where(c => c.GetType() == firstType))\n    generator.Recycle(posFor(c), 1, true);","handlingStrategy":"validation","validationCode":"var types = containers.Select(c => c.GetType()).Distinct().ToList();\nif (types.Count > 1)\n    throw new InvalidOperationException($\"Mixed container types: {string.Join(\",\", types)}\"); // recycle per-type instead","typeGuard":"static bool IsHomogeneous(IEnumerable<DependencyObject> cs) =>\n    cs.Select(c => c.GetType()).Distinct().Count() <= 1;","tryCatchPattern":"try { generator.Recycle(pos, count, true); }\ncatch (InvalidOperationException) { /* fall back: remove and regenerate instead of recycling */ }","preventionTips":["Keep container types uniform per ItemsControl (avoid template selectors that change the container CLR type).","Use VirtualizationMode.Standard when containers are heterogeneous.","Group recycle batches by container type."],"tags":["wpf","itemcontainergenerator","recycling","type-mismatch"],"backgroundTag":"type-mismatch","analyzedSha":"81131a70a4c573cd62748a5c36908fc4d662daa9","analyzedAt":"2026-09-14T10:12:48.479Z","contentChangedAt":"2026-09-14T10:12:48.479Z","schemaVersion":2},"datasetVersion":"2026-09-21T21:30:21.729Z"}