dotnet/wpf · error · InvalidOperationException
SR.Format(SR.UnexpectedValueTypeForDataTrigger…
Error message
SR.Format(SR.UnexpectedValueTypeForDataTrigger, propertyValue.ValueType)
What it means
During MultiDataTrigger.Seal(), each PropertyValue in the trigger's PropertyValues list must have a ValueType of Trigger or PropertyTriggerResource so it can be remapped to the DataTrigger variants. Any other internal PropertyValueType indicates corrupted or improperly constructed setter state, so WPF throws InvalidOperationException including the unexpected value type.
Solutions
- Build setters via the public Setters collection (Setter objects) instead of manipulating PropertyValues directly
- Do not reuse PropertyValues or Setter internals created for a different trigger type (Trigger/MultiTrigger) in a MultiDataTrigger
- Recreate the MultiDataTrigger from scratch rather than mutating its internals after construction
Example fix
// before var pv = new PropertyValue(PropertyValueType.PropertyTrigger, value); trigger.PropertyValues.Add(pv); // wrong internal type // after trigger.Setters.Add(new Setter(TextBlock.TextProperty, value));
Defensive patterns
Strategy: validation
Validate before calling
// Only build triggers through the public API
if (trigger.Setters.Count == 0 && trigger.PropertyValuesInternalCount > 0)
throw new InvalidOperationException("PropertyValues manipulated directly; use Setters"); Try / catch
try { style.Seal(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("value type")) {
// rebuild the trigger via Setters collection
} Prevention
- Construct setters only through MultiDataTrigger.Setters
- Never reuse PropertyValue structs between Trigger and DataTrigger types
- Treat trigger internals as sealed after style application
When it happens
Trigger: Programmatically constructing a MultiDataTrigger and injecting PropertyValues/Setter objects whose internal PropertyValueType is not Trigger or PropertyTriggerResource, then sealing the style; not reachable through normal XAML parsing of <MultiDataTrigger.Setters>.
Common situations: Custom framework code or styling helpers that build PropertyValue structs directly; cloning/reusing setter internals across trigger types; low-level manipulation of the sealed style machinery.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- SR.SourceNameNotSupportedForDataTriggers
- Animation_Invalid_DefaultValue
- Cannot remove signature from read-only file.
- Image_EncoderNoColorContext
- Image_EncoderNoGlobalMetadata
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/c1658199a1e0bbb4.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/MultiDataTrigger.cs:132
LogicalOp.Equals,
_conditions[i].Value);
}
// Set conditions array for all property triggers
for (int i = 0; i < PropertyValues.Count; ++i)
{
PropertyValue propertyValue = PropertyValues[i];
propertyValue.Conditions = TriggerConditions;
switch (propertyValue.ValueType)
{
case PropertyValueType.Trigger:
propertyValue.ValueType = PropertyValueType.DataTrigger;
break;
case PropertyValueType.PropertyTriggerResource:
propertyValue.ValueType = PropertyValueType.DataTriggerResource;
break;
default:
throw new InvalidOperationException(SR.Format(SR.UnexpectedValueTypeForDataTrigger, propertyValue.ValueType));
}
// Put back modified struct
PropertyValues[i] = propertyValue;
}
base.Seal();
}
// evaluate the current state of the trigger
internal override bool GetCurrentState(DependencyObject container, UncommonField<HybridDictionary[]> dataField)
{
bool retVal = (TriggerConditions.Length > 0);
for( int i = 0; retVal && i < TriggerConditions.Length; i++ )
{
retVal = TriggerConditions[i].ConvertAndMatch(StyleHelper.GetDataTriggerValue(dataField, container, TriggerConditions[i].Binding));
}View on GitHub (pinned to 81131a70a4)