dotnet/wpf · error · ArgumentException
Duplicate Stroke in StrokeCollectionChangedEventArgs.Added.
Error message
Duplicate Stroke in StrokeCollectionChangedEventArgs.Added.
What it means
Renderer.OnStrokesChanged throws ArgumentException (SR.DuplicateStrokeAdded) when a StrokeCollectionChangedEventArgs reports a stroke in its Added collection that the Renderer already tracks in its stroke-to-visual map. Each stroke must map to exactly one StrokeVisual.
Solutions
- Never add the same Stroke instance twice to a StrokeCollection
- Deep-copy or clone strokes when moving between collections
- Remove the stroke from the old collection before adding to a new one
- Check StrokeCollection.Contains before Add in custom code
Example fix
// before anotherCollection.Add(stroke); // stroke still in firstCollection // after firstCollection.Remove(stroke); anotherCollection.Add(new Stroke(stroke.StylusPoints.Clone()));
Defensive patterns
Strategy: validation
Validate before calling
// Avoid duplicate adds if (!collection.Contains(stroke)) collection.Add(stroke);
Type guard
bool CanAddSafely(StrokeCollection c, Stroke s) => s != null && !c.Contains(s);
Try / catch
try { collection.Add(stroke); }
catch (ArgumentException) { /* duplicate - ignore or log */ } Prevention
- Never Add a Stroke instance already in the collection
- Clone strokes when transferring between collections
- Route all collection mutations through one owner
- Beware re-entrant event handlers replaying Adds
When it happens
Trigger: Adding the same Stroke instance twice to a StrokeCollection, or sharing one Stroke instance across multiple StrokeCollections wired to the same Renderer/InkCanvas.
Common situations: Cloning strokes by reference instead of deep copy, moving strokes between collections by Add without Remove, event handler re-entrancy replaying an add notification.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Unrecognized Stroke in Stroke.Invalidated event arguments.
- Unrecognized Stroke in…
- SR.EventArgIsNull
- SR.EventArgIsNull
- SR.StrokeIsDuplicated
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/9011851da990e20c.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/MS/internal/Ink/Renderer.cs:436
/// <summary>
/// StrokeCollectionChanged event handler
/// </summary>
private void OnStrokesChanged(object sender, StrokeCollectionChangedEventArgs eventArgs)
{
System.Diagnostics.Debug.Assert(sender == _strokes);
// Read the args
StrokeCollection added = eventArgs.Added;
StrokeCollection removed = eventArgs.Removed;
// Add new strokes
foreach (Stroke stroke in added)
{
// Verify that it's not a dupe
if (_visuals.ContainsKey(stroke))
{
throw new System.ArgumentException(SR.DuplicateStrokeAdded);
}
// Create a visual for the new stroke and add it to the dictionary
StrokeVisual visual = new StrokeVisual(stroke, this);
_visuals.Add(stroke, visual);
// Start listening on the stroke events
StartListeningOnStrokeEvents(visual.Stroke);
// Attach it to the visual tree
AttachVisual(visual, buildingStrokeCollection: false);
}
// Deal with removed strokes first
foreach (Stroke stroke in removed)
{
// Verify that the event is in sync with the view
StrokeVisual visual = null;View on GitHub (pinned to 81131a70a4)