lepoco/wpfui · error · NullReferenceException
Element {nameof(TemplateElementToggleButton)} of type {typeo
Error message
Element {nameof(TemplateElementToggleButton)} of type {typeof(ToggleButton)} not found in {typeof(SplitButton)} What it means
During OnApplyTemplate, SplitButton looks up the named template part 'PART_SplitButtonToggleButton' and requires it to be a ToggleButton. If GetTemplateChild returns null or a non-ToggleButton, a NullReferenceException is thrown. SplitButton cannot function without this part because it drives the drop-down toggle behaviour, so a custom ControlTemplate missing it is treated as a fatal template contract violation.
Source
Thrown at src/Wpf.Ui/Controls/SplitButton/SplitButton.cs:159
}
/// <summary>This method is invoked when the <see cref="IsDropDownOpenProperty"/> changes.</summary>
/// <param name="currentValue">The new value of <see cref="IsDropDownOpenProperty"/>.</param>
protected virtual void OnIsDropDownOpenChanged(bool currentValue) { }
/// <inheritdoc />
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
if (GetTemplateChild(TemplateElementToggleButton) is ToggleButton toggleButton)
{
SplitButtonToggleButton = toggleButton;
AttachToggleButtonClick();
}
else
{
throw new NullReferenceException(
$"Element {nameof(TemplateElementToggleButton)} of type {typeof(ToggleButton)} not found in {typeof(SplitButton)}"
);
}
if (GetTemplateChild(TemplateElementToggle) is Border toggleBorder)
{
_splitButtonToggleBorder = toggleBorder;
}
}
/// <summary>
/// Triggered when the control is unloaded. Releases resource bindings.
/// </summary>
protected virtual void ReleaseTemplateResources()
{
if (SplitButtonToggleButton != null)
{
SplitButtonToggleButton.PreviewMouseLeftButtonUp -=View on GitHub (pinned to ffebacd610)
Solutions
- Include <ToggleButton x:Name="PART_SplitButtonToggleButton" /> in your custom ControlTemplate for SplitButton.
- If you do not need a custom template, remove your Style/Template so the default one is used.
- Update your template to match the template-part contract declared on SplitButton for the version you target.
Example fix
<!-- before: custom template missing the toggle -->
<ControlTemplate TargetType="{x:Type ui:SplitButton}">
<Border x:Name="PrimaryBorder" />
</ControlTemplate>
<!-- after -->
<ControlTemplate TargetType="{x:Type ui:SplitButton}">
<StackPanel Orientation="Horizontal">
<ContentPresenter />
<ToggleButton x:Name="PART_SplitButtonToggleButton" />
</StackPanel>
</ControlTemplate> Defensive patterns
Strategy: validation
Validate before calling
// Validate template before applying in design/test
var hasPart = myTemplate.LoadContent() is FrameworkElement fe
&& fe.FindName("PART_SplitButtonToggleButton") is ToggleButton;
if (!hasPart) throw new InvalidOperationException("Template missing PART_SplitButtonToggleButton"); Type guard
bool TemplateHasRequiredPart(ControlTemplate tpl, Type owner) =>
tpl.LoadContent() is FrameworkElement root && root.FindName("PART_SplitButtonToggleButton") is ToggleButton; Try / catch
try { ApplyTemplate(); }
catch (NullReferenceException ex) when (ex.Message.Contains("PART_SplitButtonToggleButton"))
{
_logger.LogError(ex, "Custom SplitButton template is missing the required toggle part.");
} Prevention
- Always copy the required PART_ elements when restyling templated controls.
- After upgrading WPF UI, diff your custom templates against the new defaults.
- Prefer Trigger-based restyling over full ControlTemplate replacement when possible.
When it happens
Trigger: Replacing the default SplitButton ControlTemplate with a custom one that omits the ToggleButton named PART_SplitButtonToggleButton, or names a control of a different type with that name.
Common situations: Restyling SplitButton and forgetting to carry over the required template part; renaming the part during a version upgrade; copying a template from a different control.
Related errors
- Template part '{name}' is not found or is not of type {typeo
- Unable to find the base directory of the application.
- Unable to determine the window source.
- Cannot change DialogHostEx while the dialog is being shown.
- DialogHost was not set
AI-assisted analysis of lepoco/wpfui@ffebacd610 (2026-08-13).
Data as JSON: /api/errors/2670f609516ae3dd.
Report an issue: GitHub.