dotnet/wpf · error · InvalidOperationException
SR.BitmapCacheBrush_RelativeTransformChanged
Error message
SR.BitmapCacheBrush_RelativeTransformChanged
What it means
BitmapCacheBrush only supports its default (null/Identity) RelativeTransform; any attempt to set a non-default transform is coerced back and throws InvalidOperationException. The library intentionally disallows changing RelativeTransform because bitmap-cache rendering cannot apply an arbitrary relative transform on the MilCore side.
Solutions
- Remove the RelativeTransform assignment and instead apply the transform to the Visual being cached or to the element's RenderTransform/LayoutTransform.
- Use RenderTransform on the BitmapCacheBrush itself or its container instead of RelativeTransform.
- If a transform is required relative to the output area, wrap the content in a decorator element that applies the transform.
Example fix
// before var brush = new BitmapCacheBrush(visual); brush.RelativeTransform = new RotateTransform(45); // after var brush = new BitmapCacheBrush(visual); brush.RenderTransform = new RotateTransform(45);
Defensive patterns
Strategy: validation
Validate before calling
static bool CanSetRelativeTransform(Transform t) => t == null || t == Transform.Identity;
Type guard
static bool IsDefaultTransform(Transform t) => t is null || t == Transform.Identity;
Prevention
- Never set RelativeTransform on BitmapCacheBrush; use RenderTransform on the brush or the cached visual instead.
- When copying brush templates between brush types, audit transform properties for BitmapCacheBrush.
- Add a style lint/test that asserts RelativeTransform remains default where BitmapCacheBrush is used.
When it happens
Trigger: Assigning a Transform to BitmapCacheBrush.RelativeTransform (directly, via binding, animation, or style setter) to any value other than the default (null/Transform.Identity).
Common situations: Data-binding or animating RelativeTransform by copying XAML patterns from other brushes (VisualBrush, ImageBrush); applying a RenderTransform-style resource to a BitmapCacheBrush in a template.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- SR.BitmapCacheBrush_TransformChanged
- SR.GeneralTransform_TransformFailed
- Animation_Invalid_DefaultValue
- Cannot remove signature from read-only file.
- Image_EncoderNoColorContext
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/a00f4fc12dba75e3.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/BitmapCacheBrush.cs:371
throw new InvalidOperationException(SR.BitmapCacheBrush_OpacityChanged);
}
return 1.0;
}
private static object CoerceTransform(DependencyObject d, object value)
{
if ((Transform)value != (Transform)TransformProperty.GetDefaultValue(typeof(BitmapCacheBrush)))
{
throw new InvalidOperationException(SR.BitmapCacheBrush_TransformChanged);
}
return null;
}
private static object CoerceRelativeTransform(DependencyObject d, object value)
{
if ((Transform)value != (Transform)RelativeTransformProperty.GetDefaultValue(typeof(BitmapCacheBrush)))
{
throw new InvalidOperationException(SR.BitmapCacheBrush_RelativeTransformChanged);
}
return null;
}
private static void StaticInitialize(Type typeofThis)
{
OpacityProperty.OverrideMetadata(typeofThis, new IndependentlyAnimatedPropertyMetadata(1.0, propertyChangedCallback: null, CoerceOpacity));
TransformProperty.OverrideMetadata(typeofThis, new UIPropertyMetadata(null, propertyChangedCallback: null, CoerceTransform));
RelativeTransformProperty.OverrideMetadata(typeofThis, new UIPropertyMetadata(null, propertyChangedCallback: null, CoerceRelativeTransform));
}
private ContainerVisual _dummyVisual;
private DispatcherOperation _DispatcherLayoutResult;
private bool _pendingLayout;
private bool _reentrancyFlag;
private bool _isAsyncRenderRegistered = false;View on GitHub (pinned to 81131a70a4)