dotnet/wpf · error · ArgumentException
SR.TableCollectionWrongProxyParent
Error message
SR.TableCollectionWrongProxyParent
What it means
When adding an item, PrivateConnectChild checks parentage. If the item's logical Parent is a DummyProxy (a lightweight parent surrogate used by table text element collections), the proxy must resolve through the logical tree to this collection's Owner. If GetParent(item.Parent) != Owner, the item already belongs to a different table/collection and ArgumentException(TableCollectionWrongProxyParent) is thrown.
Solutions
- Detach the item from its current parent first (remove it from the old collection) before adding it here.
- Create a new instance instead of reusing an element already parented elsewhere.
- Check item.Parent (and logical ancestors) before adding; only add unparented items.
Example fix
// before var row = oldTable.RowGroups[0]; newTable.RowGroups.Add(row); // throws // after var row = oldTable.RowGroups[0]; oldTable.RowGroups.Remove(row); newTable.RowGroups.Add(row);
Defensive patterns
Strategy: validation
Validate before calling
if (item.Parent != null && !(item.Parent is DummyProxy && LogicalTreeHelper.GetParent(item.Parent) == owner))
throw new InvalidOperationException("item is parented to another collection"); Type guard
static bool IsUnparentedOrOwnedBy(this TextElement item, object owner)
=> item.Parent == null
|| (item.Parent is DummyProxy && LogicalTreeHelper.GetParent(item.Parent) == owner); Prevention
- Always detach elements from their previous parent before re-parenting.
- Never share TextElement instances between two tables/documents.
- Prefer creating fresh elements over moving existing ones across trees.
- Assert item.Parent == null before Add calls in debug builds.
When it happens
Trigger: InternalAdd on an item whose Parent is a DummyProxy owned by another TableTextElementCollectionInternal — i.e. re-parenting a TableRowGroup/TableRow/Run that is already in another table.
Common situations: Moving a TableRowGroup from one Table to another without first detaching it; adding an element still referenced by a previous document/collection; sharing a child element between two tables.
Related errors
- SR.TableCollectionRangeOutOfRange
- ' ' must be the root element of a tree, but has a logical…
- Can only countersign parts with Digital Signature…
- Duplicates not allowed - signature part already exists.
- ExtendedProperty is already part of the…
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/55570f180d99c338.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/documents/TableTextElementCollectionInternal.cs:265
/// <exception cref="ArgumentException">
/// If the new item has already a parent or if the slot at the specified index is not null.
/// </exception>
/// <remarks>
/// Note that the function requires that _item[index] == null and
/// it also requires that the passed in item is not included into another ContentElementCollection.
/// </remarks>
internal override void PrivateConnectChild(int index, TElementType item)
{
Debug.Assert(item != null && item.Index == -1);
Debug.Assert(Items[index] == null);
// If the TElementType is already parented correctly through a proxy, there's no need
// to change parentage. Otherwise, it should be parented to Owner.
if (item.Parent is DummyProxy)
{
if (LogicalTreeHelper.GetParent(item.Parent) != Owner)
{
throw new System.ArgumentException(SR.TableCollectionWrongProxyParent);
}
}
// add the item into collection's array
Items[index] = item;
item.Index = index;
// notify the TElementType about the change
item.OnEnterParentTree();
}
/// <summary>
/// Notifies the TItem about the event;
/// Disconnects the item from the model tree;
/// Sets the TItem's slot in the collection's array to null.
/// </summary>
internal override void PrivateDisconnectChild(TElementType item)View on GitHub (pinned to 81131a70a4)