mirror of
https://github.com/microsoft/microsoft-ui-xaml.git
synced 2026-10-28 16:35:19 +08:00
## Fixes | Internal issue | Type | Change | |---|---|---| | https://task.ms/64475625 | Bug | Column headers are a templated, restylable `TableViewColumnHeader` with visual states | | https://task.ms/64475623 | Bug | Header typography comes from the header Style, not C++ local values | | https://task.ms/64143451 | Bug | Header column separators are always drawn (no new property); hide them by overriding `TabularSurfaceHeaderSeparatorBrush` | | https://task.ms/63996584 | Task | Column headers expose the UIA Transform pattern so UIA clients can resize columns | | https://task.ms/64475611 | Bug | Outer border uses new `TabularSurfaceOuterBorderBrush` (`CardStrokeColorDefault`); grid-line values were in #12349 | | https://task.ms/64475629 | Bug | Default group header uses theme tokens (SemiBold key style, 8px spacing); the item count inherits the header `Foreground` | | https://task.ms/64652961 | Task | Row recycling no longer regenerates cells or refreshes row chrome twice (scroll performance) | | https://task.ms/63790855 | Task | Sort: `CanSort` is enforced and `SortByColumn(column, None)` always clears; a sort through a source another table owns returns false; no spurious `Sorted`; an app-owned sort survives a `CanSort`/`CanUserSortColumns` opt-out | | https://task.ms/63787021 | Task | Cell automation-peer constructor validates its arguments; `BeginEdit` rolls back when it throws | Not changed: https://task.ms/64512732 (by design: Auto columns follow content width), https://task.ms/64475627 (design decision: keep chevron sort glyphs), https://task.ms/64513223 (investigation only; fix deferred). ## PR Type - [x] Bugfix - [x] Feature - [ ] Code style update (formatting, renaming) - [ ] Refactoring (no functional changes, no API changes) - [ ] Build related changes - [x] Documentation content changes - [ ] Other (please describe): ## Description Follow-up to #12349 (merged) and #12285. Column headers move from code-built Grids to a new templated `TableViewColumnHeader`, restylable through `TableView.ColumnHeaderStyle` or `TableViewColumn.HeaderStyle`. Header peers gain the UIA Transform pattern for column resize. Sort behavior is tightened around `CanSort`, opt-outs and shared `TableViewSource` ownership. Row recycling reuses cells. Outer border, header lines and the default group header follow Fluent tokens. Review-driven fixes included here: - The header Style's `TargetType` `TypeName` is kept alive while it is compared; a Style with only `BasedOn` typed is applied, and its setters are read before applying it seals the Style. Incompatible, untyped or cyclic `BasedOn` Styles are ignored with a debug diagnostic. - A header disabled by its Style reports `IsEnabled=false` and is not invokable through UIA. - UIA `Transform.Resize` converts physical pixels through the table's full visual scale (not only `RasterizationScale`), and a width change below the drag jitter deadband is written once, exactly. - Disabling a header in its High Contrast hover/pressed state keeps the disabled foreground (state order fixed); the disabled sort glyph follows the text brush across theme changes. - A `CanSort` opt-out made inside `BeginningEdit` is replayed after the edit it let open closes, and rebuilds headers even when a `Sorted` handler throws. - Header rebuilds caused by `Content`/`Header` or `Columns` changes keep focus in the header band, respect an app's own focus move, and release `UIElement` headers back to the app. - A disabled group header does not dim its item count twice. The count opacity follows `ContentTemplate` changes while the header is disabled. <details><summary>Product changes by file</summary> | File | +/- | What changed | Items | |---|---|---|---| | `TableView/TableView.cpp` (+ .h) | +684 / −382 | `RebuildHeaders` creates `TableViewColumnHeader` controls; applies `ColumnHeaderStyle`/`HeaderStyle` with TargetType/BasedOn checks; density MinHeight/Padding only when the Style doesn't set them<br>`ReleaseHeaderCells` and header-focus handling for removed/replaced columns, re-entrant rebuilds and app focus moves<br>Header bottom rule thickness set on `PART_HeaderRow`; header lines no longer follow `GridLinesVisibility`<br>Row prepare/clear refresh chrome once; `TryResizeColumnFromAutomation` writes small widths exactly | 64475625, 64475623, 64143451, 64652961, 63996584, 63790855 | | `TableView/TableViewColumnHeader.cpp` (+ .h; replaces `TableViewHeaderCell.h`) | +435 / −210 | New sealed templated `ContentControl` with read-only `Column`<br>Resolves `PART_ContentPresenter`, `PART_GridLine`, `PART_SortIndicatorHost`, `PART_ResizeGripperHost`; hosts the sort glyph and gripper<br>Drives `CommonStates`/`HighContrastStates`/`SortStates`; disabled sort glyph bound to the text brush | 64475625, 64475623 | | `TableView/TableViewRow.cpp` (+ .h) | +191 / −35 | Recycled rows keep their cells unless cell automation peers exist; chrome refreshed once; tooltips re-applied on recycle<br>`BeginCellEdit` restores display element, edit state and focus on throw | 64652961, 63787021 | | `TableView/TableView.xaml` | +128 / −18 | Default `TableViewColumnHeader` Style/template: typography setters, visual states, parts<br>Outer border uses `TabularSurfaceOuterBorderBrush`; header lines use `TabularSurfaceHeaderSeparatorBrush`<br>Group header: `TableViewGroupExpanderSpacing` (8), padding 8,8,12,8, key/count text styles, count inherits `Foreground` | 64475625, 64475623, 64475611, 64475629 | | `TableView/TableViewColumnHeaderAutomationPeer.cpp` (+ .h) | +127 / −9 | `ITransformProvider`: `Resize` converts physical px through the visual scale; `CanResize` tracks gripper availability (pinned → false)<br>`IsEnabled` follows the header; name read from the content presenter | 63996584, 64475625 | | `TableView/TableView_Sort.cpp` | +113 / −39 | `SortByColumn(None)` bypasses the `CanSort` gate; other sorts refused<br>Sort through a source owned by another table returns false; implicit clears keep the app's sort and raise no `Sorted`; app-lit columns left alone on opt-out | 63790855 | | `TableView/TableView_Layout.cpp` | +74 / −14 | Realized-row walk only when a visible Auto column exists<br>Transform `CanResize` changes raised for existing header peers | 64652961, 63996584 | | `TableView/TableView_Editing.cpp` | +63 / −15 | `BeginEdit` unwinds on throw; `CanSort` opt-out during `BeginningEdit` queued until the edit closes | 63787021, 63790855 | | `TableView/TableViewCellAutomationPeer.cpp` (+ .h, `TableViewCell.h`) | +48 / −0 | Public constructor throws `E_INVALIDARG` for null args, negative/out-of-range index or a foreign column; internal path uses `TrustedOwnerTag` | 63787021 | | `TableView/TableViewGroupHeader.cpp` (+ .h) | +39 / −0 | Default count's opacity is not applied twice when disabled | 64475629 | | `TableView/TableView.idl` | +31 / −13 | `TableViewColumnHeader`, `TableView.ColumnHeaderStyle`, `TableViewColumn.HeaderStyle`<br>`CanSort`/`SortByColumn`/`ToggleSortDirection`/`GridLinesVisibility` docs; cell-peer `E_INVALIDARG`; group-header parts | 64475625, 63790855, 64143451, 63787021 | | `TableView/TableView_Columns.cpp` | +19 / −0 | Releases removed columns' header cells; old `UIElement` `Header` returned to the app on change | 64475625 | | `TableView/TableViewColumn.cpp` | +7 / −0 | `HeaderStyle` change queues a header rebuild | 64475625 | | `TableView/TableViewSource.h` | +6 / −0 | `IsOwnedByOther` helper for sort sync | 63790855 | | `CommonStyles/TabularSurfaces_themeresources.xaml` | +5 / −2 | New `TabularSurfaceOuterBorderBrush` (Dark/Light/HC); group count opacity documented as secondary-over-primary text (0.77 Dark) | 64475611, 64475629 | | `TableView/TableView.vcxitems` | +2 / −1 | Swap `TableViewHeaderCell.h` for `TableViewColumnHeader.*` | 64475625 | | Generated / metadata (`Generated/TableView.properties.*`, `Generated/TableViewColumn.properties.*`, `dll-tabular/XamlMetadataProviderGenerated.h`) | +123 / −0 | Codegen for the new properties and type | 64475625 | **Total: 17 rows, 29 product files, +2117 / −738.** Also: 19 test files (+3718 / −32), 3 docs (+161 / −35), 6 sample files (+2 / −9). </details> ### New preview API (needs API review) - **`TableViewColumnHeader`**: sealed, templated `ContentControl`, created only by `TableView`. - Read-only `Column` property. - Template parts (optional): `PART_ContentPresenter`, `PART_GridLine`, `PART_SortIndicatorHost`, `PART_ResizeGripperHost`. - Visual state groups: `CommonStates`, `HighContrastStates`, `SortStates`. - **`TableView.ColumnHeaderStyle`**: Style applied to every column header. - **`TableViewColumn.HeaderStyle`**: per-column Style; wins over `TableView.ColumnHeaderStyle`. There is no `HeaderGridLinesVisibility` property. `GridLinesVisibility` affects body lines only; header lines are always drawn. To hide them, override `TabularSurfaceHeaderSeparatorBrush` with `Transparent`. ### Current Behavior - Headers are built in C++ with no template, no visual states and forced local typography, so apps can't restyle them. Header separators don't show. - Header peers report `HeaderItem` without Transform, so UIA clients can't resize columns. - `SortByColumn` ignores `CanSort`; `CanSort=false` on a sorted column leaves the sort in place; sorting through a source another table owns reports success; some implicit clears raise `Sorted(None)` while the app's sort remains. - The cell peer constructor accepts invalid arguments; a throw in `BeginEdit` leaves edit state half-open. - Recycling a row rebuilt every cell, refreshed chrome up to twice and invalidated the table's measure. - The outer border has no dedicated brush; the default group header uses raw weights and off-grid spacing. ### New Behavior - Headers use the templated `TableViewColumnHeader` (see API above); typography, padding and brushes come from Style setters. - Header peers implement `ITransformProvider` through the existing resize path (Min/Max clamping, scale conversion; pinned columns report `CanResize=false`). - `CanSort=false` blocks header clicks, `SortByColumn` (except `None`) and `ToggleSortDirection`, and clears the column's own active sort; sorts through a source owned by another table return false; `Sorted` is raised only when the table's sort state changes. - Cell peer constructor throws `E_INVALIDARG` on bad input; `BeginEdit` rolls back on failure. - Recycled rows reuse their cells unless cell automation peers exist; chrome refreshes once. > **Visible changes** > - Outer border uses `CardStrokeColorDefault`. > - Header lines are always shown, even when `GridLinesVisibility` is `None` or `Horizontal`. > - Group header restyled: 8px spacing; the count follows the header `Foreground`. > - Disabled header text and sort glyph dim. > - TableView samples no longer opt out of High Contrast backplates app-wide. ## Customer Impact Restylable column headers, visible header separators, Fluent-aligned outer border and group headers, UIA column resize for assistive technology, smoother scrolling and predictable sort events. ## Regression Potential - [ ] Low risk — isolated change, limited scope - [x] Medium risk — touches shared components or public APIs - [ ] High risk — architectural or breaking API change Header construction (focus restore, frozen columns, UIA peer, tooltips, resize, sort glyph) moved to a templated control. Sort event semantics are tighter: `CanSort` is enforced on programmatic sorts and fewer `Sorted` events fire. Outer border color and always-on header lines change visibly. Covered by new and existing tests. ## How Has This Been Tested? - [x] I have performed a self-review of my own code - [x] I have added tests to cover my changes - [x] Existing tests pass locally Full TableView API and interaction suites on test VMs: 877/882 pass at 224d10d5c; 3 Localization tests are [Ignore] and 2 intermittent failures passed 3/3 on rerun. Product, test apps and TableView sample apps build (x64 chk). Also covered: `VerifyDisabledGroupHeaderCountFollowsContentTemplateChanges`. Key new tests: - `VerifyColumnHeaderTemplateParts`, `VerifyColumnHeaderSortStates`, `VerifyColumnHeaderTypographyHasNoLocalValues` - `VerifyColumnHeaderStyleApplies`, `VerifyBasedOnOnlyColumnHeaderStyleApplies`, `VerifyIncompatibleColumnHeaderStyleIsIgnored` - `VerifyHeaderGridLinesShowWhateverTheBodyGridLines`, `VerifyTransparentHeaderSeparatorBrushHidesHeaderLines`, `VerifyGridLineAndOuterBorderBrushesMatchFluentStrokeTokens` - `VerifyDisablingHighContrastHoveredHeaderKeepsDisabledForeground`, `VerifyDefaultGroupHeaderCountInheritsForegroundThatFollowsStates` - `VerifyTransformResizeAccountsForAncestorScale`, `VerifyTransformResizeSmallWidthChangeWritesOnce`, `VerifyHeaderDisabledByStyleIsNotEnabledOrInvokable` - `VerifySortByColumnRespectsCanSort`, `VerifyImplicitClearKeepsSourceSort`, `VerifyUngatingKeepsAppLitColumnWithoutEvents`, `VerifySortOptOutDuringBeginningEditKeepsTheEditOpen` - `VerifyRecycledRowWithoutCellPeersReusesItsCells`, `VerifyHeaderFocusStaysInHeaderBandWhenColumnsReplaced`, `VerifyBeginEditThatThrowsRollsBackAndAllowsALaterEdit`, `VerifyCellPeerConstructorValidatesArguments` --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 94961bb8-d187-483c-bece-19e203752c67
611 lines
44 KiB
XML
611 lines
44 KiB
XML
<!-- Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License. See LICENSE in the project root for license information. -->
|
|
<ResourceDictionary
|
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
|
xmlns:controls="using:Microsoft.UI.Xaml.Controls">
|
|
|
|
<Thickness x:Key="TableViewHeaderCellPadding">8,4,8,4</Thickness>
|
|
<!-- Metric defaults remain available alongside the default styles. -->
|
|
<x:Double x:Key="TableViewResizeGripperWidth">8</x:Double>
|
|
|
|
<!-- TabularControlsResources is required to supply TabularSurface* brushes for all themes. -->
|
|
|
|
<!-- TableView default style. Header cells stack horizontally (one per
|
|
column); the body is an ItemsRepeater of TableViewRow, each building its cells from
|
|
the owning TableView's Columns. -->
|
|
<Style TargetType="controls:TableView">
|
|
<!-- The control is a focus SCOPE, not a focus STOP: Tab must land on the header band and
|
|
then the body, never on the table element itself. Matches the ListView default style
|
|
(dxaml\xcp\dxaml\themes\generic.xaml), which sets IsTabStop="False" for the same
|
|
reason. Control.IsTabStop defaults to true, so this has to be stated.
|
|
|
|
Deliberately NOT paired with TabNavigation="Once". ListView sets that because it wants
|
|
exactly ONE stop for the whole control; TableView wants TWO - the header band and the
|
|
body - and Once here would swallow the body, leaving it unreachable by Tab. The two
|
|
stops come from the two bands owning their own scopes: KeyboardNavigationMode::Once on
|
|
PART_HeaderHost (TableView::OnApplyTemplate) and the same mode that ItemsRepeater sets
|
|
on itself for PART_RowsRepeater. -->
|
|
<Setter Property="IsTabStop" Value="False" />
|
|
<Setter Property="CornerRadius" Value="{ThemeResource ControlCornerRadius}" />
|
|
<Setter Property="Background" Value="{ThemeResource TabularSurfaceRowBackgroundBrush}" />
|
|
<Setter Property="Foreground" Value="{ThemeResource TabularSurfaceRowForegroundBrush}" />
|
|
<Setter Property="BorderBrush" Value="{ThemeResource TabularSurfaceOuterBorderBrush}" />
|
|
<Setter Property="BorderThickness" Value="1" />
|
|
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
|
|
<Setter Property="VerticalContentAlignment" Value="Stretch" />
|
|
<Setter Property="Template">
|
|
<Setter.Value>
|
|
<ControlTemplate TargetType="controls:TableView">
|
|
<Border Background="{TemplateBinding Background}"
|
|
BorderBrush="{TemplateBinding BorderBrush}"
|
|
BorderThickness="{TemplateBinding BorderThickness}"
|
|
CornerRadius="{TemplateBinding CornerRadius}">
|
|
<Grid>
|
|
<Grid.RowDefinitions>
|
|
<RowDefinition Height="Auto" />
|
|
<RowDefinition Height="*" />
|
|
</Grid.RowDefinitions>
|
|
<Border x:Name="PART_HeaderRow"
|
|
Grid.Row="0"
|
|
Background="{ThemeResource TabularSurfaceHeaderBackgroundBrush}"
|
|
BorderBrush="{ThemeResource TabularSurfaceHeaderSeparatorBrush}"
|
|
BorderThickness="0,0,0,1">
|
|
<Grid>
|
|
<ScrollViewer x:Name="PART_HeaderScroller"
|
|
HorizontalScrollMode="Disabled"
|
|
VerticalScrollMode="Disabled"
|
|
HorizontalScrollBarVisibility="Hidden"
|
|
VerticalScrollBarVisibility="Disabled">
|
|
<!-- Left, not the default Stretch: the panel reports the summed column
|
|
width, and a wider presenter would centre it. PART_CellsHost
|
|
must match. -->
|
|
<controls:TableViewCellsPanel x:Name="PART_HeaderHost"
|
|
HorizontalAlignment="Left" />
|
|
</ScrollViewer>
|
|
</Grid>
|
|
</Border>
|
|
<ScrollViewer x:Name="PART_BodyScroller"
|
|
Grid.Row="1"
|
|
HorizontalScrollMode="Auto"
|
|
HorizontalScrollBarVisibility="Auto"
|
|
VerticalScrollMode="Auto"
|
|
VerticalScrollBarVisibility="Auto"
|
|
VerticalContentAlignment="Stretch">
|
|
|
|
<Grid x:Name="PART_BodyContent" Background="Transparent">
|
|
<ItemsRepeater x:Name="PART_RowsRepeater"
|
|
VerticalCacheLength="2.0">
|
|
<ItemsRepeater.Layout>
|
|
<StackLayout Orientation="Vertical" />
|
|
</ItemsRepeater.Layout>
|
|
</ItemsRepeater>
|
|
<ContentControl x:Name="PART_EmptyStatePresenter"
|
|
Visibility="Collapsed"
|
|
IsTabStop="False"
|
|
HorizontalAlignment="Stretch"
|
|
VerticalAlignment="Stretch"
|
|
HorizontalContentAlignment="Center"
|
|
VerticalContentAlignment="Center" />
|
|
</Grid>
|
|
</ScrollViewer>
|
|
</Grid>
|
|
</Border>
|
|
</ControlTemplate>
|
|
</Setter.Value>
|
|
</Setter>
|
|
</Style>
|
|
|
|
<Style TargetType="controls:TableViewColumnHeader">
|
|
<Setter Property="IsTabStop" Value="True" />
|
|
<Setter Property="UseSystemFocusVisuals" Value="True" />
|
|
<!-- Without a fill the padding takes no pointer input, killing the tooltip and click-to-sort there. -->
|
|
<Setter Property="Background" Value="Transparent" />
|
|
<Setter Property="FontSize" Value="{ThemeResource TableViewHeaderFontSize}" />
|
|
<Setter Property="FontWeight" Value="{ThemeResource TableViewHeaderFontWeight}" />
|
|
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
|
|
<Setter Property="VerticalContentAlignment" Value="Center" />
|
|
<Setter Property="Template">
|
|
<Setter.Value>
|
|
<ControlTemplate TargetType="controls:TableViewColumnHeader">
|
|
<!-- CornerRadius is set only while keyboard-focused: a rounded root clips. -->
|
|
<Grid x:Name="PART_Root"
|
|
Background="{TemplateBinding Background}"
|
|
CornerRadius="{TemplateBinding CornerRadius}">
|
|
<!-- See TableViewRow: state groups must sit on the template root. -->
|
|
<VisualStateManager.VisualStateGroups>
|
|
<VisualStateGroup x:Name="CommonStates">
|
|
<VisualState x:Name="Normal" />
|
|
<VisualState x:Name="PointerOver">
|
|
<VisualState.Setters>
|
|
<Setter Target="PART_Root.Background" Value="{ThemeResource TabularSurfaceHeaderBackgroundPointerOverBrush}" />
|
|
</VisualState.Setters>
|
|
</VisualState>
|
|
<VisualState x:Name="Pressed">
|
|
<VisualState.Setters>
|
|
<Setter Target="PART_Root.Background" Value="{ThemeResource TabularSurfaceHeaderBackgroundPressedBrush}" />
|
|
</VisualState.Setters>
|
|
</VisualState>
|
|
<VisualState x:Name="Disabled">
|
|
<VisualState.Setters>
|
|
<Setter Target="PART_ContentPresenter.Foreground" Value="{ThemeResource TabularSurfaceRowForegroundDisabledBrush}" />
|
|
</VisualState.Setters>
|
|
</VisualState>
|
|
</VisualStateGroup>
|
|
|
|
<VisualStateGroup x:Name="HighContrastStates">
|
|
<VisualState x:Name="HighContrastNormal" />
|
|
<VisualState x:Name="HighContrastPointerOver">
|
|
<VisualState.Setters>
|
|
<Setter Target="PART_ContentPresenter.Foreground" Value="{ThemeResource TabularSurfaceHeaderForegroundPointerOverBrush}" />
|
|
<Setter Target="PART_ContentPresenter.HighContrastAdjustment" Value="None" />
|
|
</VisualState.Setters>
|
|
</VisualState>
|
|
<VisualState x:Name="HighContrastPressed">
|
|
<VisualState.Setters>
|
|
<Setter Target="PART_ContentPresenter.Foreground" Value="{ThemeResource TabularSurfaceHeaderForegroundPressedBrush}" />
|
|
<Setter Target="PART_ContentPresenter.HighContrastAdjustment" Value="None" />
|
|
</VisualState.Setters>
|
|
</VisualState>
|
|
</VisualStateGroup>
|
|
|
|
<VisualStateGroup x:Name="SortStates">
|
|
<VisualState x:Name="Unsorted" />
|
|
<VisualState x:Name="SortAscending">
|
|
<VisualState.Setters>
|
|
<Setter Target="PART_SortIndicatorHost.Visibility" Value="Visible" />
|
|
</VisualState.Setters>
|
|
</VisualState>
|
|
<VisualState x:Name="SortDescending">
|
|
<VisualState.Setters>
|
|
<Setter Target="PART_SortIndicatorHost.Visibility" Value="Visible" />
|
|
</VisualState.Setters>
|
|
</VisualState>
|
|
</VisualStateGroup>
|
|
</VisualStateManager.VisualStateGroups>
|
|
|
|
<ContentPresenter x:Name="PART_ContentPresenter"
|
|
Content="{TemplateBinding Content}"
|
|
ContentTemplate="{TemplateBinding ContentTemplate}"
|
|
ContentTemplateSelector="{TemplateBinding ContentTemplateSelector}"
|
|
ContentTransitions="{TemplateBinding ContentTransitions}"
|
|
Padding="{TemplateBinding Padding}"
|
|
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
|
|
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
|
|
AutomationProperties.AccessibilityView="Raw" />
|
|
|
|
<Border x:Name="PART_GridLine"
|
|
Width="1"
|
|
HorizontalAlignment="Right"
|
|
Background="{ThemeResource TabularSurfaceHeaderSeparatorBrush}"
|
|
IsHitTestVisible="False"
|
|
Visibility="Collapsed"
|
|
AutomationProperties.AccessibilityView="Raw" />
|
|
|
|
<Border x:Name="PART_SortIndicatorHost"
|
|
HorizontalAlignment="Right"
|
|
VerticalAlignment="Center"
|
|
IsHitTestVisible="False"
|
|
Visibility="Collapsed"
|
|
AutomationProperties.AccessibilityView="Raw" />
|
|
|
|
<!-- Last, so the gripper wins the hit test on the shared edge. -->
|
|
<Border x:Name="PART_ResizeGripperHost" />
|
|
</Grid>
|
|
</ControlTemplate>
|
|
</Setter.Value>
|
|
</Setter>
|
|
</Style>
|
|
|
|
<x:Double x:Key="TableViewRowExpanderSize">24</x:Double>
|
|
|
|
<!-- Indent added per hierarchy level on a tree row's first column. Override in an app's
|
|
resources to retheme every table, or in one TableView's Resources for a single table. -->
|
|
<x:Double x:Key="TableViewRowIndentSize">16</x:Double>
|
|
|
|
<Style TargetType="controls:TableViewRow">
|
|
<!-- The row IS a focus target. Body navigation is TWO-LEVEL, following the W3C ARIA APG
|
|
`treegrid` pattern: focus enters the body on a ROW, Right drills into that row's first
|
|
CELL, and Left from the first cell comes back out to the ROW. So Control.IsTabStop's
|
|
default of true is what we want here and there is deliberately no setter overriding it.
|
|
|
|
The row's IsTabStop is not static, though: TableViewRow::SetCellLevelInternal clears it
|
|
for exactly as long as the cursor is drilled into that row's cells, and restores it on
|
|
the way back out. That is what keeps the body ONE tab stop in BOTH directions - see the
|
|
comment on SetCellLevelInternal for why the framework's tab walk forces the trade. -->
|
|
<Setter Property="CornerRadius" Value="{ThemeResource ControlCornerRadius}" />
|
|
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
|
|
<Setter Property="Background" Value="{ThemeResource TabularSurfaceRowBackgroundBrush}" />
|
|
<Setter Property="BorderBrush" Value="{ThemeResource TabularSurfaceGridLineBrush}" />
|
|
<Setter Property="BorderThickness" Value="0,0,0,1" />
|
|
<Setter Property="UseSystemFocusVisuals" Value="True" />
|
|
<Setter Property="Template">
|
|
<Setter.Value>
|
|
<ControlTemplate TargetType="controls:TableViewRow">
|
|
<Grid>
|
|
<!-- State groups belong on the TEMPLATE ROOT: VisualStateManager resolves
|
|
them from the root's attached property, so hosting them on an inner
|
|
element disables every state silently - no parse error and no warning,
|
|
just a row that never paints its selected / hover / pressed visuals. -->
|
|
<VisualStateManager.VisualStateGroups>
|
|
<VisualStateGroup x:Name="CommonStates">
|
|
<VisualState x:Name="Normal" />
|
|
<VisualState x:Name="PointerOver">
|
|
<Storyboard>
|
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PART_RootBorder" Storyboard.TargetProperty="Background">
|
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TabularSurfaceRowBackgroundPointerOverBrush}" />
|
|
</ObjectAnimationUsingKeyFrames>
|
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PART_CellForegroundPresenter" Storyboard.TargetProperty="Foreground">
|
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TabularSurfaceRowForegroundPointerOverBrush}" />
|
|
</ObjectAnimationUsingKeyFrames>
|
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PART_CellForegroundPresenter" Storyboard.TargetProperty="HighContrastAdjustment">
|
|
<DiscreteObjectKeyFrame KeyTime="0" Value="None" />
|
|
</ObjectAnimationUsingKeyFrames>
|
|
</Storyboard>
|
|
</VisualState>
|
|
<VisualState x:Name="Pressed">
|
|
<Storyboard>
|
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PART_RootBorder" Storyboard.TargetProperty="Background">
|
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TabularSurfaceRowBackgroundPressedBrush}" />
|
|
</ObjectAnimationUsingKeyFrames>
|
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PART_CellForegroundPresenter" Storyboard.TargetProperty="Foreground">
|
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TabularSurfaceRowForegroundPressedBrush}" />
|
|
</ObjectAnimationUsingKeyFrames>
|
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PART_CellForegroundPresenter" Storyboard.TargetProperty="HighContrastAdjustment">
|
|
<DiscreteObjectKeyFrame KeyTime="0" Value="None" />
|
|
</ObjectAnimationUsingKeyFrames>
|
|
</Storyboard>
|
|
</VisualState>
|
|
<VisualState x:Name="Disabled">
|
|
<Storyboard>
|
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PART_RootBorder" Storyboard.TargetProperty="Background">
|
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TabularSurfaceRowBackgroundDisabledBrush}" />
|
|
</ObjectAnimationUsingKeyFrames>
|
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PART_CellForegroundPresenter" Storyboard.TargetProperty="Foreground">
|
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TabularSurfaceRowForegroundDisabledBrush}" />
|
|
</ObjectAnimationUsingKeyFrames>
|
|
</Storyboard>
|
|
</VisualState>
|
|
<!-- Selected states live in this SAME group rather than a second one:
|
|
they animate the same PART_RootBorder.Background, and two groups
|
|
would make the result depend on GoToState call order. One group
|
|
whose names encode both dimensions is the pattern TreeViewItem
|
|
and ItemContainer use. -->
|
|
<VisualState x:Name="Selected">
|
|
<Storyboard>
|
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PART_RootBorder" Storyboard.TargetProperty="Background">
|
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TabularSurfaceRowBackgroundSelectedBrush}" />
|
|
</ObjectAnimationUsingKeyFrames>
|
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PART_CellForegroundPresenter" Storyboard.TargetProperty="Foreground">
|
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TabularSurfaceRowForegroundSelectedBrush}" />
|
|
</ObjectAnimationUsingKeyFrames>
|
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PART_CellForegroundPresenter" Storyboard.TargetProperty="HighContrastAdjustment">
|
|
<DiscreteObjectKeyFrame KeyTime="0" Value="None" />
|
|
</ObjectAnimationUsingKeyFrames>
|
|
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="PART_SelectionIndicator" Storyboard.TargetProperty="Opacity">
|
|
<LinearDoubleKeyFrame KeyTime="0:0:0.083" Value="1" />
|
|
</DoubleAnimationUsingKeyFrames>
|
|
</Storyboard>
|
|
</VisualState>
|
|
<VisualState x:Name="SelectedPointerOver">
|
|
<Storyboard>
|
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PART_RootBorder" Storyboard.TargetProperty="Background">
|
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TabularSurfaceRowBackgroundSelectedPointerOverBrush}" />
|
|
</ObjectAnimationUsingKeyFrames>
|
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PART_CellForegroundPresenter" Storyboard.TargetProperty="Foreground">
|
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TabularSurfaceRowForegroundSelectedPointerOverBrush}" />
|
|
</ObjectAnimationUsingKeyFrames>
|
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PART_CellForegroundPresenter" Storyboard.TargetProperty="HighContrastAdjustment">
|
|
<DiscreteObjectKeyFrame KeyTime="0" Value="None" />
|
|
</ObjectAnimationUsingKeyFrames>
|
|
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="PART_SelectionIndicator" Storyboard.TargetProperty="Opacity">
|
|
<LinearDoubleKeyFrame KeyTime="0:0:0.083" Value="1" />
|
|
</DoubleAnimationUsingKeyFrames>
|
|
</Storyboard>
|
|
</VisualState>
|
|
<VisualState x:Name="SelectedPressed">
|
|
<Storyboard>
|
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PART_RootBorder" Storyboard.TargetProperty="Background">
|
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TabularSurfaceRowBackgroundSelectedPressedBrush}" />
|
|
</ObjectAnimationUsingKeyFrames>
|
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PART_CellForegroundPresenter" Storyboard.TargetProperty="Foreground">
|
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TabularSurfaceRowForegroundSelectedPressedBrush}" />
|
|
</ObjectAnimationUsingKeyFrames>
|
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PART_CellForegroundPresenter" Storyboard.TargetProperty="HighContrastAdjustment">
|
|
<DiscreteObjectKeyFrame KeyTime="0" Value="None" />
|
|
</ObjectAnimationUsingKeyFrames>
|
|
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="PART_SelectionIndicator" Storyboard.TargetProperty="Opacity">
|
|
<LinearDoubleKeyFrame KeyTime="0:0:0.083" Value="1" />
|
|
</DoubleAnimationUsingKeyFrames>
|
|
</Storyboard>
|
|
</VisualState>
|
|
<VisualState x:Name="SelectedDisabled">
|
|
<Storyboard>
|
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PART_RootBorder" Storyboard.TargetProperty="Background">
|
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TabularSurfaceRowBackgroundDisabledBrush}" />
|
|
</ObjectAnimationUsingKeyFrames>
|
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PART_CellForegroundPresenter" Storyboard.TargetProperty="Foreground">
|
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TabularSurfaceRowForegroundDisabledBrush}" />
|
|
</ObjectAnimationUsingKeyFrames>
|
|
<!-- Suppress the High Contrast text backplate wherever the row paints a state fill (hover, press, selection). -->
|
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PART_CellForegroundPresenter" Storyboard.TargetProperty="HighContrastAdjustment">
|
|
<DiscreteObjectKeyFrame KeyTime="0" Value="None" />
|
|
</ObjectAnimationUsingKeyFrames>
|
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PART_SelectionIndicator" Storyboard.TargetProperty="Fill">
|
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TabularSurfaceSelectionIndicatorDisabledBrush}" />
|
|
</ObjectAnimationUsingKeyFrames>
|
|
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="PART_SelectionIndicator" Storyboard.TargetProperty="Opacity">
|
|
<LinearDoubleKeyFrame KeyTime="0:0:0.083" Value="1" />
|
|
</DoubleAnimationUsingKeyFrames>
|
|
</Storyboard>
|
|
</VisualState>
|
|
</VisualStateGroup>
|
|
|
|
<!-- Hierarchy groups. Inert for flat/grouped sources (Level 0). -->
|
|
<VisualStateGroup x:Name="RowExpansionStates">
|
|
<VisualState x:Name="RowCollapsed">
|
|
<VisualState.Setters>
|
|
<Setter Target="PART_RowExpanderIcon.Glyph" Value="" />
|
|
</VisualState.Setters>
|
|
</VisualState>
|
|
<VisualState x:Name="RowExpanded">
|
|
<VisualState.Setters>
|
|
<Setter Target="PART_RowExpanderIcon.Glyph" Value="" />
|
|
</VisualState.Setters>
|
|
</VisualState>
|
|
</VisualStateGroup>
|
|
|
|
<VisualStateGroup x:Name="RowExpandabilityStates">
|
|
<VisualState x:Name="RowExpandable" />
|
|
<!-- Only the glyph hides; the gutter keeps its width so leaf text
|
|
aligns with sibling branch text. -->
|
|
<VisualState x:Name="RowNotExpandable">
|
|
<VisualState.Setters>
|
|
<Setter Target="PART_RowExpanderIcon.Visibility" Value="Collapsed" />
|
|
</VisualState.Setters>
|
|
</VisualState>
|
|
</VisualStateGroup>
|
|
|
|
<VisualStateGroup x:Name="RowHierarchyStates">
|
|
<!-- TableViewRow sets gutter Visibility directly; these states exist
|
|
for retemplating apps to key off. -->
|
|
<VisualState x:Name="RowNotHierarchical" />
|
|
<VisualState x:Name="RowHierarchical" />
|
|
</VisualStateGroup>
|
|
</VisualStateManager.VisualStateGroups>
|
|
|
|
<Border x:Name="PART_RootBorder"
|
|
Grid.Row="0"
|
|
Grid.Column="0"
|
|
Background="{TemplateBinding Background}"
|
|
BorderThickness="{TemplateBinding BorderThickness}"
|
|
Padding="{TemplateBinding Padding}">
|
|
<Grid>
|
|
<!-- Cell host. TableViewRow populates PART_CellsHost with one cell wrapper
|
|
per TableViewColumn, in Columns order, laid out left-to-right.
|
|
The presenter exists so the Selected* states have something with a
|
|
Foreground to animate: PART_RootBorder is a Border and has none, and
|
|
cell text inherits Foreground down from here. Without it the selected
|
|
foreground brushes are unreachable, which is only cosmetic in
|
|
light/dark (the selected fill is ~4% alpha) but makes a selected row
|
|
illegible in High Contrast, where the fill is the opaque
|
|
SystemColorHighlightColor. -->
|
|
<ContentPresenter x:Name="PART_CellForegroundPresenter"
|
|
Foreground="{TemplateBinding Foreground}"
|
|
HorizontalContentAlignment="Stretch"
|
|
VerticalContentAlignment="Stretch">
|
|
<Grid>
|
|
<!-- Left, matching PART_HeaderHost. -->
|
|
<controls:TableViewCellsPanel x:Name="PART_CellsHost"
|
|
HorizontalAlignment="Left" />
|
|
|
|
<!-- Hierarchy chevron. Overlays the first cell (TableViewRow pads it by
|
|
the same indent) so cells stay aligned with headers; later child so it
|
|
stays on top as the hit target. No own Foreground: inherits the
|
|
presenter's, keeping this optional part out of CommonStates. -->
|
|
<Border x:Name="PART_RowExpanderGutter"
|
|
Width="{ThemeResource TableViewRowExpanderSize}"
|
|
Background="Transparent"
|
|
HorizontalAlignment="Left"
|
|
VerticalAlignment="Stretch"
|
|
Visibility="Collapsed">
|
|
<FontIcon x:Name="PART_RowExpanderIcon"
|
|
FontSize="12"
|
|
Glyph=""
|
|
MirroredWhenRightToLeft="True"
|
|
HorizontalAlignment="Center"
|
|
VerticalAlignment="Center" />
|
|
</Border>
|
|
</Grid>
|
|
</ContentPresenter>
|
|
|
|
<!-- Fluent selection indicator: overlays the leading edge, Opacity 0 by
|
|
default; the Selected* states animate it to 1. Not hit-testable, so it
|
|
cannot steal a press from the cell underneath it. -->
|
|
<Rectangle x:Name="PART_SelectionIndicator"
|
|
Width="3"
|
|
Height="16"
|
|
RadiusX="1.5"
|
|
RadiusY="1.5"
|
|
Fill="{ThemeResource TabularSurfaceSelectionIndicatorBrush}"
|
|
HorizontalAlignment="Left"
|
|
VerticalAlignment="Center"
|
|
Margin="2,0,0,0"
|
|
IsHitTestVisible="False"
|
|
Opacity="0" />
|
|
</Grid>
|
|
</Border>
|
|
<Border x:Name="PART_GridLineBorder"
|
|
Grid.Row="0"
|
|
Grid.Column="0"
|
|
BorderBrush="{TemplateBinding BorderBrush}"
|
|
BorderThickness="{TemplateBinding BorderThickness}"
|
|
IsHitTestVisible="False" />
|
|
</Grid>
|
|
</ControlTemplate>
|
|
</Setter.Value>
|
|
</Setter>
|
|
</Style>
|
|
<!--
|
|
TableViewGroupHeader. The ControlTemplate owns the band chrome and the chevron
|
|
(PART_ExpanderGutter / PART_ExpanderIcon); PART_ContentPresenter is the only
|
|
app-customizable region, showing ContentTemplate over the TableViewGroupInfo Content.
|
|
|
|
ContentTemplate always resolves: the default Style seeds it, and
|
|
TableView.GroupHeaderTemplate overrides it as a local value that ClearValue reverts. So
|
|
there is no default-vs-custom branch, and an app template cannot drop the expander or
|
|
the band. Expansion, enabled and pointer state are VisualStates, so the chevron glyph
|
|
is declared here rather than assigned from C++.
|
|
-->
|
|
<x:Double x:Key="TableViewGroupExpanderSize">24</x:Double>
|
|
<!-- Gap between the expander gutter and the content; root rows are indented by size + spacing. -->
|
|
<x:Double x:Key="TableViewGroupExpanderSpacing">8</x:Double>
|
|
<Thickness x:Key="TableViewGroupHeaderPadding">8,8,12,8</Thickness>
|
|
|
|
<!-- BodyStrongTextBlockStyle equivalent, single line. -->
|
|
<Style x:Key="TableViewGroupHeaderKeyTextStyle" TargetType="TextBlock">
|
|
<Setter Property="FontWeight" Value="SemiBold" />
|
|
<Setter Property="TextTrimming" Value="CharacterEllipsis" />
|
|
<Setter Property="TextWrapping" Value="NoWrap" />
|
|
<Setter Property="VerticalAlignment" Value="Center" />
|
|
</Style>
|
|
|
|
<!-- Opacity is a Style setter, not a local value, so TableViewGroupHeader can override it while disabled and clear it back. -->
|
|
<Style x:Key="TableViewGroupHeaderCountTextStyle" TargetType="TextBlock">
|
|
<Setter Property="Opacity" Value="{ThemeResource TabularSurfaceGroupHeaderCountOpacity}" />
|
|
<Setter Property="VerticalAlignment" Value="Center" />
|
|
</Style>
|
|
|
|
<DataTemplate x:Key="TableViewDefaultGroupHeaderContentTemplate">
|
|
<StackPanel x:Name="TableViewDefaultGroupHeaderContentRoot" Orientation="Horizontal" Spacing="8" VerticalAlignment="Center">
|
|
<TextBlock Text="{Binding KeyText, Mode=OneWay}"
|
|
Style="{StaticResource TableViewGroupHeaderKeyTextStyle}" />
|
|
<!-- Inherits Foreground so it follows the header's states and an app's Foreground. -->
|
|
<TextBlock x:Name="TableViewGroupHeaderItemCountText"
|
|
Text="{Binding ItemCountText, Mode=OneWay}"
|
|
Style="{StaticResource TableViewGroupHeaderCountTextStyle}" />
|
|
</StackPanel>
|
|
</DataTemplate>
|
|
|
|
<Style TargetType="controls:TableViewGroupHeader">
|
|
<Setter Property="Background" Value="{ThemeResource TabularSurfaceGroupHeaderBackgroundBrush}" />
|
|
<Setter Property="Foreground" Value="{ThemeResource TabularSurfaceGroupHeaderForegroundBrush}" />
|
|
<Setter Property="BorderBrush" Value="{ThemeResource TabularSurfaceGroupHeaderBorderBrush}" />
|
|
<Setter Property="BorderThickness" Value="{ThemeResource TabularSurfaceGroupHeaderBorderThickness}" />
|
|
<Setter Property="Padding" Value="{ThemeResource TableViewGroupHeaderPadding}" />
|
|
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
|
|
<Setter Property="VerticalContentAlignment" Value="Center" />
|
|
<!-- Focusable so keyboard users can expand/collapse: TableViewGroupHeader::OnKeyDown
|
|
handles Enter/Space (toggle) and Right/Left (expand/collapse), matching TreeViewItem. -->
|
|
<Setter Property="IsTabStop" Value="True" />
|
|
<Setter Property="UseSystemFocusVisuals" Value="True" />
|
|
<Setter Property="CornerRadius" Value="{ThemeResource ControlCornerRadius}" />
|
|
<Setter Property="ContentTemplate" Value="{StaticResource TableViewDefaultGroupHeaderContentTemplate}" />
|
|
<Setter Property="Template">
|
|
<Setter.Value>
|
|
<ControlTemplate TargetType="controls:TableViewGroupHeader">
|
|
<Grid>
|
|
<!-- See TableViewRow: state groups must sit on the template root. -->
|
|
<VisualStateManager.VisualStateGroups>
|
|
<VisualStateGroup x:Name="CommonStates">
|
|
<VisualState x:Name="Normal" />
|
|
<VisualState x:Name="PointerOver">
|
|
<VisualState.Setters>
|
|
<Setter Target="PART_Root.Background" Value="{ThemeResource TabularSurfaceRowBackgroundPointerOverBrush}" />
|
|
<Setter Target="PART_ContentPresenter.Foreground" Value="{ThemeResource TabularSurfaceRowForegroundPointerOverBrush}" />
|
|
<Setter Target="PART_ExpanderIcon.Foreground" Value="{ThemeResource TabularSurfaceRowForegroundPointerOverBrush}" />
|
|
<Setter Target="PART_ContentPresenter.HighContrastAdjustment" Value="None" />
|
|
<Setter Target="PART_ExpanderIcon.HighContrastAdjustment" Value="None" />
|
|
</VisualState.Setters>
|
|
</VisualState>
|
|
<VisualState x:Name="Pressed">
|
|
<VisualState.Setters>
|
|
<Setter Target="PART_Root.Background" Value="{ThemeResource TabularSurfaceRowBackgroundPressedBrush}" />
|
|
<Setter Target="PART_ContentPresenter.Foreground" Value="{ThemeResource TabularSurfaceRowForegroundPressedBrush}" />
|
|
<Setter Target="PART_ExpanderIcon.Foreground" Value="{ThemeResource TabularSurfaceRowForegroundPressedBrush}" />
|
|
<Setter Target="PART_ContentPresenter.HighContrastAdjustment" Value="None" />
|
|
<Setter Target="PART_ExpanderIcon.HighContrastAdjustment" Value="None" />
|
|
</VisualState.Setters>
|
|
</VisualState>
|
|
<VisualState x:Name="Disabled">
|
|
<VisualState.Setters>
|
|
<Setter Target="PART_ContentPresenter.Foreground" Value="{ThemeResource TabularSurfaceRowForegroundDisabledBrush}" />
|
|
<Setter Target="PART_ExpanderIcon.Foreground" Value="{ThemeResource TabularSurfaceRowForegroundDisabledBrush}" />
|
|
</VisualState.Setters>
|
|
</VisualState>
|
|
</VisualStateGroup>
|
|
|
|
<VisualStateGroup x:Name="ExpansionStates">
|
|
<VisualState x:Name="Collapsed">
|
|
<VisualState.Setters>
|
|
<Setter Target="PART_ExpanderIcon.Glyph" Value="" />
|
|
</VisualState.Setters>
|
|
</VisualState>
|
|
<VisualState x:Name="Expanded">
|
|
<VisualState.Setters>
|
|
<Setter Target="PART_ExpanderIcon.Glyph" Value="" />
|
|
</VisualState.Setters>
|
|
</VisualState>
|
|
</VisualStateGroup>
|
|
|
|
<VisualStateGroup x:Name="ExpandabilityStates">
|
|
<VisualState x:Name="Expandable" />
|
|
<VisualState x:Name="NotExpandable">
|
|
<!-- Only the chevron hides; PART_ExpanderGutter keeps its width so
|
|
content stays aligned across expandable and non-expandable groups. -->
|
|
<VisualState.Setters>
|
|
<Setter Target="PART_ExpanderIcon.Visibility" Value="Collapsed" />
|
|
</VisualState.Setters>
|
|
</VisualState>
|
|
</VisualStateGroup>
|
|
</VisualStateManager.VisualStateGroups>
|
|
|
|
<Border x:Name="PART_Root"
|
|
Grid.Row="0"
|
|
Grid.Column="0"
|
|
Background="{TemplateBinding Background}"
|
|
BorderThickness="{TemplateBinding BorderThickness}"
|
|
Padding="{TemplateBinding Padding}"
|
|
HorizontalAlignment="Stretch">
|
|
<Grid ColumnSpacing="{ThemeResource TableViewGroupExpanderSpacing}">
|
|
<Grid.ColumnDefinitions>
|
|
<ColumnDefinition Width="Auto" />
|
|
<ColumnDefinition Width="*" />
|
|
</Grid.ColumnDefinitions>
|
|
|
|
<!-- The chevron is a pure visual. The whole band is the toggle target
|
|
(TableViewGroupHeader::OnPointerReleased), matching ListView /
|
|
TreeView, so there is no nested Button to inflate, focus or name. -->
|
|
<Border x:Name="PART_ExpanderGutter"
|
|
Grid.Column="0"
|
|
Width="{ThemeResource TableViewGroupExpanderSize}">
|
|
<FontIcon x:Name="PART_ExpanderIcon"
|
|
FontSize="12"
|
|
Foreground="{TemplateBinding Foreground}"
|
|
MirroredWhenRightToLeft="True"
|
|
HorizontalAlignment="Center"
|
|
VerticalAlignment="Center" />
|
|
</Border>
|
|
|
|
<ContentPresenter x:Name="PART_ContentPresenter"
|
|
Grid.Column="1"
|
|
Content="{TemplateBinding Content}"
|
|
ContentTemplate="{TemplateBinding ContentTemplate}"
|
|
Foreground="{TemplateBinding Foreground}"
|
|
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
|
|
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" />
|
|
</Grid>
|
|
</Border>
|
|
<Border x:Name="PART_GridLineBorder"
|
|
Grid.Row="0"
|
|
Grid.Column="0"
|
|
BorderBrush="{TemplateBinding BorderBrush}"
|
|
BorderThickness="{TemplateBinding BorderThickness}"
|
|
IsHitTestVisible="False" />
|
|
</Grid>
|
|
</ControlTemplate>
|
|
</Setter.Value>
|
|
</Setter>
|
|
</Style>
|
|
|
|
</ResourceDictionary>
|