Skip to content

Feat: Add weeknumbers to Calendar - #21311

Closed
timunie wants to merge 11 commits into
AvaloniaUI:mainfrom
timunie:feat/CalendarWeekNumbers
Closed

Feat: Add weeknumbers to Calendar#21311
timunie wants to merge 11 commits into
AvaloniaUI:mainfrom
timunie:feat/CalendarWeekNumbers

Conversation

@timunie

@timunie timunie commented May 4, 2026

Copy link
Copy Markdown
Collaborator

What does the pull request do?

Adds week number display to both Calendar and CalendarDatePicker in month view (Fluent and Simple themes).

Calendar with week numbers

What is the current behavior?

Calendar and CalendarDatePicker only show day-of-week headers and date cells in month view. There is no way to display week numbers alongside the calendar grid.

What is the updated/expected behavior with this PR?

  • A new week-number column can be shown on the left side of the month grid by setting IsWeekNumberVisible="True".
  • The column header is configurable via WeekNumberHeader (e.g. "#", "CW", "KW", "Wk" — defaults to "#").
  • The week numbering rule is configurable via WeekNumberRule using the new CalendarWeekNumberRule enum. Use WeekNumberRule="Iso" for ISO 8601 week numbering; other values (FirstDay, FirstFullWeek, FirstFourDayWeek) map to the BCL equivalents. Defaults to the current culture's rule.
  • All properties are mirrored on CalendarDatePicker, where they propagate to the inner popup calendar.
  • The calendar does not shrink when switching from month view to year/decade view. A new :hasweeknumbers pseudo-class on CalendarItem is used in the Fluent theme to hold the minimum width stable.

How was the solution implemented?

New type — CalendarWeekNumberLabel (Avalonia.Controls.Primitives)

A ContentControl subclass placed in column 0 of PART_MonthView. Exposes a :header pseudo-class for the top cell (row 0) so themes can style it differently from the data cells (rows 1–6).

New enum — CalendarWeekNumberRule (Avalonia.Controls)

Avalonia-specific enum replacing the BCL CalendarWeekRule on the WeekNumberRule property, with an additional Iso value:

public enum CalendarWeekNumberRule
{
    FirstDay = 0,         // maps to CalendarWeekRule.FirstDay
    FirstFullWeek = 1,    // maps to CalendarWeekRule.FirstFullWeek
    FirstFourDayWeek = 2, // maps to CalendarWeekRule.FirstFourDayWeek
    Iso = 3,              // explicit ISO 8601 shorthand
}

API diff

// Avalonia.Controls.Calendar — 3 new properties
+public static readonly StyledProperty<bool> IsWeekNumberVisibleProperty;
+public bool IsWeekNumberVisible { get; set; }                       // default: false

+public static readonly StyledProperty<CalendarWeekNumberRule> WeekNumberRuleProperty;
+public CalendarWeekNumberRule WeekNumberRule { get; set; }          // default: current culture

+public static readonly StyledProperty<object?> WeekNumberHeaderProperty;
+public object? WeekNumberHeader { get; set; }                       // default: "#"


// Avalonia.Controls.CalendarDatePicker — same 3 properties via AddOwner
+public static readonly StyledProperty<bool> IsWeekNumberVisibleProperty;
+public bool IsWeekNumberVisible { get; set; }

+public static readonly StyledProperty<CalendarWeekNumberRule> WeekNumberRuleProperty;
+public CalendarWeekNumberRule WeekNumberRule { get; set; }

+public static readonly StyledProperty<object?> WeekNumberHeaderProperty;
+public object? WeekNumberHeader { get; set; }


// Avalonia.Controls.Primitives.CalendarItem — new pseudo-class
-[PseudoClasses(":calendardisabled")]
+[PseudoClasses(":calendardisabled", ":hasweeknumbers")]


// Avalonia.Controls.Primitives.CalendarWeekNumberLabel — new public type
+public sealed class CalendarWeekNumberLabel : ContentControl
+{
+    public bool IsHeader { get; internal set; }  // sets :header pseudo-class
+}

// Avalonia.Controls/Calendar/DateTimeHelper.cs
+public static int GetWeekOfYear(DateTime date, CalendarWeekNumberRule rule, DayOfWeek firstDayOfWeek)

ISO 8601 week number fix — DateTimeHelper.GetWeekOfYear

.NET's Calendar.GetWeekOfYear with FirstFourDayWeek + Monday incorrectly returns week 53 for late-December dates that ISO 8601 assigns to week 1 of the next year (e.g. 2018-12-31 → ISO week 1 of 2019). Both the Iso shorthand and the explicit FirstFourDayWeek + Monday combination delegate to ISOWeek.GetWeekOfYear to avoid this bug:

public static int GetWeekOfYear(DateTime date, CalendarWeekNumberRule rule, DayOfWeek firstDayOfWeek)
{
    var mappedRule = (System.Globalization.CalendarWeekRule)(int)rule;

    if (rule == CalendarWeekNumberRule.Iso ||
        (mappedRule == CalendarWeekRule.FirstFourDayWeek && firstDayOfWeek == DayOfWeek.Monday))
        return ISOWeek.GetWeekOfYear(date);

    return CultureInfo.CurrentCulture.Calendar.GetWeekOfYear(date, mappedRule, firstDayOfWeek);
}

Checklist

Breaking changes

None.

Obsoletions / Deprecations

None.

Fixed issues

Fixes #7976

@timunie timunie added enhancement api-needs-review The PR adds new public APIs that should be reviewed. labels May 4, 2026
@avaloniaui-bot

Copy link
Copy Markdown

You can test this PR using the following package version. 12.1.999-cibuild0065222-alpha. (feed url: https://nuget-feed-all.avaloniaui.net/v3/index.json) [PRBUILDID]

Comment thread src/Avalonia.Controls/Calendar/DateTimeHelper.cs Outdated
@timunie
timunie requested a review from Copilot May 6, 2026 15:20
@timunie
timunie marked this pull request as ready for review May 6, 2026 15:20
@avaloniaui-bot

Copy link
Copy Markdown

You can test this PR using the following package version. 12.1.999-cibuild0065248-alpha. (feed url: https://nuget-feed-all.avaloniaui.net/v3/index.json) [PRBUILDID]

Comment thread src/Avalonia.Controls/Calendar/Calendar.cs Outdated
Comment thread src/Avalonia.Controls/Calendar/CalendarItem.cs Outdated
Comment thread src/Avalonia.Controls/Calendar/CalendarWeekNumberLabel.cs Outdated
Comment thread src/Avalonia.Controls/Calendar/DateTimeHelper.cs Outdated
Comment thread src/Avalonia.Controls/CalendarDatePicker/CalendarDatePicker.Properties.cs Outdated
Comment on lines +405 to +406
<StaticResource x:Key="CalendarViewWeekNumberSeparatorForeground"
ResourceKey="SystemControlDisabledBaseMediumLowBrush" />

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As mentioned above, if the CalendarWeekNumberLabel goes away it would be needed to add CalendarViewWeekNumberForeground and related resources here.

/// the appearance — for example <c>FontWeight="Bold"</c>.
/// Use the <c>:header</c> pseudo-class to target the column header cell (row 0).
/// </summary>
public sealed class CalendarWeekNumberLabel : ContentControl

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO an entire new primitive probably isn't needed for this concept. It can be done with text and light-weight styling resources alone.

That in turn allows room for future expansion in this area. For example -- we might want to make it interactive as a button in some way, the calendar might get a week ONLY view, etc.

I'm also not a fan of the legacy term "Label" being used for new controls. That just isn't done in modern XAML.

Comment thread src/Avalonia.Controls/Calendar/Calendar.cs Outdated
@timunie
timunie force-pushed the feat/CalendarWeekNumbers branch from 0e2f4d5 to 49d4f91 Compare May 21, 2026 20:06
@avaloniaui-bot

Copy link
Copy Markdown

You can test this PR using the following package version. 12.1.999-cibuild0065706-alpha. (feed url: https://nuget-feed-all.avaloniaui.net/v3/index.json) [PRBUILDID]

@MrJul

MrJul commented Aug 13, 2026

Copy link
Copy Markdown
Member

Notes from the API review meeting:

  • Remove WeekNumberHeader from all controls. Keep the header blank for now. Users can customize the template if needed.
  • Remove CalendarWeekNumberRule: use the framework CalendarWeekRule instead. The internal fix (CalendarWeekRule.FirstFourDayWeek && DayOfWeek.Monday) can remain to ensure ISO-compatibility.
  • Remove CalendarWeekNumberLabel: use some ContentControl instead.

@MrJul MrJul added api-needs-changes The new public APIs need some changes. and removed api-needs-review The PR adds new public APIs that should be reviewed. labels Aug 13, 2026
@timunie
timunie force-pushed the feat/CalendarWeekNumbers branch from 40a12c6 to 30bb9f4 Compare August 13, 2026 13:50
@avaloniaui-bot

Copy link
Copy Markdown

You can test this PR using the following package version. 12.2.999-cibuild0068294-alpha. (feed url: https://nuget-feed-all.avaloniaui.net/v3/index.json) [PRBUILDID]

@timunie timunie closed this Aug 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api-needs-changes The new public APIs need some changes. enhancement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Calendar with week numbers

4 participants