Fall back to the solid color when the background image can't load#150
Merged
Conversation
If a background image was set and then deleted, moved, replaced with a non-image file, or put on an unavailable share, the ImageBrush failed silently and the clock rendered with no background at all - unreadable text on the bare desktop. The empty-path solid-color fallback never applied because the path wasn't empty. Build the background through a converter that tries the image and falls back to the solid outer color whenever it can't be loaded; a valid image still renders exactly as before.
There was a problem hiding this comment.
Pull request overview
This PR fixes a WPF rendering gap where a configured-but-unloadable background image results in a fully transparent clock background, by centralizing brush creation logic into a converter that can reliably fall back to a solid color.
Changes:
- Added
BackgroundBrushConverterto build the background brush and fall back toOuterColorwhen image loading fails. - Replaced
Borderstyle triggers inMainWindow.xamlwith aMultiBindingto the new converter.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| DesktopClock/Utilities/BackgroundBrushConverter.cs | Introduces an IMultiValueConverter that attempts to load the background image eagerly and falls back to a solid brush when loading fails. |
| DesktopClock/MainWindow.xaml | Switches background selection logic from XAML triggers to a MultiBinding using the new converter. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+59
to
+63
| catch | ||
| { | ||
| // Missing file, non-image content, unavailable share, or a malformed path all fall back to the solid color. | ||
| return null; | ||
| } |
Owner
Author
There was a problem hiding this comment.
Keeping the bare catch here, deliberately:
- It matches the intent exactly. The contract is "if the image can't be produced for any reason, fall back to the solid color" — the same all-or-nothing semantics the previous XAML binding had (WPF's binding engine swallowed every load failure silently). Enumerating exception types just risks missing one (
UriFormatException,FileNotFoundException,NotSupportedException,IOException,UnauthorizedAccessException,ArgumentExceptionare all reachable from this block) and turning a bad path into a crash on someone's machine. - It's the established pattern in this codebase — e.g.
Tokenizer.FormatWithTokenizerOrFallBack,Settings.Save/LoadFromFile/FileChanged,MainWindow.CopyToClipboard/TryPlaySound,ThemeManager.ApplyTitleBarThemeall use barecatchfor graceful fallback. A critical-exception filter here would be the only one of its kind. - The critical-exception concern is mostly theoretical on net481:
ThreadAbortExceptionautomatically re-throws at the end of a catch block, and a process-fatal OOM won't be meaningfully rescued by one converter propagating it.
If the project ever adopts a repo-wide exception-filter convention this spot should follow it, but I don't think this PR is the place to introduce a one-off.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
When a background image is set and then becomes unreadable — the file is deleted, moved, replaced with a non-image file (the picker offers an "All files" filter), or lives on an unavailable network share — the
ImageBrushfails to load, WPF swallows the error, and the brush paints nothing. The clock is left with a fully transparent background and no outline, so e.g. white text sits directly on the desktop with no backing and can be unreadable.The existing solid-color fallback only triggered when the path was empty, so a set-but-broken path fell through to a blank background.
Fixed by building the background brush through a small
IMultiValueConverter(BackgroundBrushConverter) instead of the style triggers:ImageBrush, exactly as before.OuterColor.The image is loaded with
BitmapCacheOption.OnLoadinside atry/catch, so a bad file fails predictably (and the file isn't held open). A valid image renders identically to before, including transparent gaps with Uniform/None stretch.