Is your feature request related to a problem? Please describe.
When a View has SchemeName set to a custom scheme name and the active theme doesn't define that name, View.GetScheme() throws a KeyNotFoundException. This happens in common real-world situations:
- A developer registers a custom scheme and sets
SchemeName on their views, then the user switches to a built-in theme that doesn't include the custom scheme.
- An end-user edits their config file and makes a typo in a scheme name.
- An end-user deletes a custom scheme from their config, or upgrades to a version of the library where a scheme was renamed.
- I found this to be an issue because I define several custom schemes for specific views - ListViews and ScrollBars are a prime example - and if I don't use a custom theme, my app crashes.
There is also an asymmetry: a view without SchemeName already falls back gracefully (SuperView → Base), but a view with SchemeName throws immediately if the name isn't found.
Reproduction:
SchemeManager.AddScheme("MyScheme", new Scheme { Normal = new Attribute(Color.Cyan, Color.Black) });
view.SchemeName = "MyScheme";
// Later — switch to a theme that doesn't define "MyScheme":
ThemeManager.Theme = "Dark";
ConfigurationManager.Apply();
view.GetScheme(); // KeyNotFoundException
This is also discussed in #4457.
Describe the solution you'd like
When SchemeName is set but the named scheme is not found in the active theme, View.GetScheme() should fall back gracefully through the following chain (consistent with how a view without SchemeName already behaves):
- Named scheme — if found in the active theme, use it
SuperView.GetScheme() — inherit from the parent view (recursive)
"Base" scheme from the active theme
- Hard-coded
"Base" — always available regardless of config state
A warning should be written to the diagnostic log when a fallback occurs, so developers can detect misconfigured SchemeName values without a crash.
New API addition to SchemeManager:
// Non-throwing counterpart to GetScheme(string).
// Returns false if the scheme is missing or CM is not in a resolvable state.
public static bool TryGetScheme(string schemeName, [NotNullWhen(true)] out Scheme? scheme)
GetScheme(string) is left unchanged to preserve backward compatibility.
Describe alternatives you've considered
- Throw with a better message — still crashes the app; not acceptable for a theme switch.
- Return
null from GetScheme() — would be a breaking API change and propagate null-handling throughout the codebase.
- Validate
SchemeName at assignment time — the scheme may not exist yet, or may be removed later; validation at set-time is the wrong layer.
Additional context
See discussion #4457 for the original proposal and proof-of-concept.
Is your feature request related to a problem? Please describe.
When a
ViewhasSchemeNameset to a custom scheme name and the active theme doesn't define that name,View.GetScheme()throws aKeyNotFoundException. This happens in common real-world situations:SchemeNameon their views, then the user switches to a built-in theme that doesn't include the custom scheme.There is also an asymmetry: a view without
SchemeNamealready falls back gracefully (SuperView → Base), but a view withSchemeNamethrows immediately if the name isn't found.Reproduction:
This is also discussed in #4457.
Describe the solution you'd like
When
SchemeNameis set but the named scheme is not found in the active theme,View.GetScheme()should fall back gracefully through the following chain (consistent with how a view withoutSchemeNamealready behaves):SuperView.GetScheme()— inherit from the parent view (recursive)"Base"scheme from the active theme"Base"— always available regardless of config stateA warning should be written to the diagnostic log when a fallback occurs, so developers can detect misconfigured
SchemeNamevalues without a crash.New API addition to
SchemeManager:GetScheme(string)is left unchanged to preserve backward compatibility.Describe alternatives you've considered
nullfromGetScheme()— would be a breaking API change and propagate null-handling throughout the codebase.SchemeNameat assignment time — the scheme may not exist yet, or may be removed later; validation at set-time is the wrong layer.Additional context
See discussion #4457 for the original proposal and proof-of-concept.