MaterialDesignInXAML/MaterialDesignInXamlToolkit · error · ArgumentOutOfRangeException
MinuteSelectionStep must be a divisor of 60 and between 1 an
Error message
MinuteSelectionStep must be a divisor of 60 and between 1 and 60.
What it means
`Clock.MinuteSelectionStep` is a `DependencyProperty` whose change callback validates the new int: it must be in [1,60] and divide 60 evenly, else `ArgumentOutOfRangeException`. Because the validation lives in the property-changed callback (not a `ValidateValueCallback`), an invalid value set via XAML/binding is assigned first and then the callback throws, which can surface as an unhandled XAML parse or binding exception.
Source
Thrown at src/MaterialDesignThemes.Wpf/Clock.cs:250
nameof(CornerRadius), typeof(CornerRadius), typeof(Clock), new PropertyMetadata(default(CornerRadius)));
public CornerRadius CornerRadius
{
get => (CornerRadius)GetValue(CornerRadiusProperty);
set => SetValue(CornerRadiusProperty, value);
}
public static readonly DependencyProperty MinuteSelectionStepProperty = DependencyProperty.Register(
nameof(MinuteSelectionStep), typeof(int),typeof(Clock), new PropertyMetadata(1, MinuteSelectionStepPropertyChangedCallback));
private static void MinuteSelectionStepPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var clock = (Clock)d;
int step = (int)e.NewValue;
if (step < 1 || step > 60 || 60 % step != 0)
throw new ArgumentOutOfRangeException(
nameof(MinuteSelectionStep),
$"{nameof(MinuteSelectionStep)} must be a divisor of 60 and between 1 and 60.");
clock.GenerateButtons();
}
public int MinuteSelectionStep
{
get => (int)GetValue(MinuteSelectionStepProperty);
set => SetValue(MinuteSelectionStepProperty, value);
}
public static readonly RoutedEvent ClockChoiceMadeEvent =
EventManager.RegisterRoutedEvent(
"ClockChoiceMade",
RoutingStrategy.Bubble,
typeof(ClockChoiceMadeEventHandler),
typeof(Clock));View on GitHub (pinned to 98edec3a0b)
Solutions
- Use a valid divisor of 60 within 1-60: 1, 2, 3, 4, 5, 6, 10, 12, 15, 20, 30, or 60.
- Constrain the source of any binding to that same set (an enum or validated combo box).
- If allowing arbitrary steps, snap to the nearest valid divisor before assigning.
- Consider replacing the throw with `CoerceValueCallback` that clamps the value, so invalid input degrades gracefully instead of throwing.
Example fix
// before <mdtc:Clock MinuteSelectionStep="7" /> <!-- throws --> // after <mdtc:Clock MinuteSelectionStep="5" />
Defensive patterns
Strategy: validation
Validate before calling
static readonly HashSet<int> ValidSteps =
new() { 1, 2, 3, 4, 5, 6, 10, 12, 15, 20, 30, 60 };
int step = desiredStep;
if (!ValidSteps.Contains(step)) step = 1; // safe default
clock.MinuteSelectionStep = step; Type guard
static bool IsValidMinuteStep(int step)
=> step >= 1 && step <= 60 && 60 % step == 0; Prevention
- Restrict MinuteSelectionStep to divisors of 60 within 1-60.
- Bind from a constrained source (enum/combo) so invalid values can't be chosen.
- Prefer a CoerceValueCallback over throwing in the changed callback for dependency properties.
When it happens
Trigger: Setting `MinuteSelectionStep` to 0, a value > 60, or a non-divisor of 60 such as 7, 9, 11, 13; providing it via XAML attribute, style setter, or binding.
Common situations: User/designer types `MinuteSelectionStep="7"` in XAML thinking any minute step works; binding to a preference that allows arbitrary ints; copying a value from a 24-hour or seconds-based control.
Related errors
- Non primary hues provided.
- kinds must contain at least one value
- Must specify two values
- Value must be positive
- Password cannot be empty
AI-assisted analysis of MaterialDesignInXAML/MaterialDesignInXamlToolkit@98edec3a0b (2026-08-13).
Data as JSON: /api/errors/8a04a0f33c4ccd60.
Report an issue: GitHub.