dotnet/wpf · error
ScrollViewer marked as PART_ContentHost must have no…
Error message
ScrollViewer marked as PART_ContentHost must have no content.
What it means
When PasswordBox applies its control template, SetRenderScopeToContentHost attaches the internal PasswordTextBox render scope to the PART_ContentHost element. If that part is a ScrollViewer that already has Content, WPF throws NotSupportedException because the content host must be empty to host the password render scope.
Solutions
- Remove all content from the PART_ContentHost ScrollViewer in the template
- Add watermarks/hints as sibling elements overlaying the content host, not as its Content
- Use TemplateBinding-free, empty ScrollViewer exactly named PART_ContentHost with ScrollViewer.Content = null
- Base the custom template on the stock PasswordBox template rather than the TextBox one
Example fix
// before
<ScrollViewer x:Name="PART_ContentHost">
<TextBlock Text="Enter password"/> <!-- throws -->
</ScrollViewer>
// after
<Grid>
<ScrollViewer x:Name="PART_ContentHost"/>
<TextBlock Text="Enter password" IsHitTestVisible="False" Visibility="{Binding Text, Converter=...}"/>
</Grid> Defensive patterns
Strategy: validation
Validate before calling
var sv = templateChild as ScrollViewer; bool ok = sv != null && sv.Content == null; // PART_ContentHost must be an empty ScrollViewer
Type guard
bool isEmptyContentHost(FrameworkElement fe) =>
(fe is ScrollViewer sv && sv.Content == null) || (fe is Decorator d && d.Child == null); Prevention
- Keep PART_ContentHost ScrollViewer childless in PasswordBox templates
- Implement watermark/placeholder visuals as overlay siblings, not content-host children
- Start custom templates from the stock PasswordBox template
- Avoid reusing TextBox templates verbatim for PasswordBox
When it happens
Trigger: A custom PasswordBox ControlTemplate whose ScrollViewer named PART_ContentHost contains child content (elements or inline content set on ScrollViewer.Content), triggering template application (InitializeRenderScope).
Common situations: Copying a TextBox template and adding decorations inside the PART_ContentHost ScrollViewer; blending a TextBlock watermark inside the content host; hand-edited templates after upgrading from a TextBox template.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- Decorator marked as PART_ContentHost must have no content.
- Only Decorator and ScrollViewer can be used as…
- ElementNotEnabledException
- InvalidOperationException (no message)
- InvalidOperationException
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/46b6bde25112faf4.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/PasswordBox.cs:940
{
// Clear the content host from previous render scope (if any)
ClearContentHost();
// Find ContentHostTemplateName in the style
_passwordBoxContentHost = GetTemplateChild(ContentHostTemplateName) as FrameworkElement;
// Note that we allow ContentHostTemplateName to be optional.
// This simplifies toolability of our control styling.
// When the ContentHostTemplateName is not found or incorrect
// PasswordBox goes into disabled state, but does not throw.
// Add renderScope as a child of ContentHostTemplateName
_renderScope = renderScope;
if (_passwordBoxContentHost is ScrollViewer scrollViewer)
{
if (scrollViewer.Content != null)
{
throw new NotSupportedException(SR.TextBoxScrollViewerMarkedAsTextBoxContentMustHaveNoContent);
}
else
{
scrollViewer.Content = _renderScope;
}
}
else if (_passwordBoxContentHost is Decorator decorator)
{
if (decorator.Child != null)
{
throw new NotSupportedException(SR.TextBoxDecoratorMarkedAsTextBoxContentMustHaveNoContent);
}
else
{
decorator.Child = _renderScope; // this may replace old render scope in case of upgrade scenario in TextBox
}
}
elseView on GitHub (pinned to 81131a70a4)