Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 0 additions & 8 deletions components/DataTable/samples/DataTable.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,6 @@ can be made to look like a table of data:
There are limitations here with having fixed column sizes that can be difficult to align. Their definitions are
also duplicated, and every item is recreating this layout and duplicating it within the Visual Tree.

## DataRow Hybrid Setup

As a first step, moving to **DataTable** is easy, just replace the `Grid` in your `ItemsTemplate` with the `DataRow` panel
and remove the Column attributes from your controls. `DataRow` automatically will lay each subsequent control in the next column
for you automatically:

> [!Sample DataTableHybridSample]

## DataTable Setup

The `DataTable` setup provides an easier way to define and manage your columns within your header for this coordinated effort
Expand Down
50 changes: 0 additions & 50 deletions components/DataTable/samples/DataTableHybridSample.xaml

This file was deleted.

48 changes: 0 additions & 48 deletions components/DataTable/samples/DataTableHybridSample.xaml.cs

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<!-- Sets this up as a toolkit component's source project -->
<Import Project="$(ToolingDirectory)\ToolkitComponent.SourceProject.props" />

<PropertyGroup>
<PropertyGroup>
<PackageId>$(PackageIdPrefix).$(PackageIdVariant).Controls.$(ToolkitComponentName)</PackageId>
</PropertyGroup>
</Project>
66 changes: 48 additions & 18 deletions components/DataTable/src/DataTable/DataColumn.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,40 @@

namespace CommunityToolkit.WinUI.Controls;

/// <summary>
/// Column of <see cref="DataTable"/>.
/// </summary>
[TemplatePart(Name = nameof(PART_ColumnSizer), Type = typeof(ContentSizer))]
public partial class DataColumn : ContentControl
{
private static GridLength StarLength = new GridLength(1, GridUnitType.Star);

private ContentSizer? PART_ColumnSizer;

private WeakReference<DataTable>? _parent;

internal DataTable? DataTable => _parent?.TryGetTarget(out DataTable? parent) == true ? parent : null;

/// <summary>
/// Gets or sets the width of the largest child contained within the visible <see cref="DataRow"/>s of the <see cref="DataTable"/>.
/// Gets or sets the internal calculated or manually set width of this column.
/// - Positive value: this column has a fixed or manually set width.
/// - Negative value: this column has a calculated width which is derived from DesiredWidth.
/// - NaN: this column should have a calculated width which isn't set yet.
/// </summary>
internal double MaxChildDesiredWidth { get; set; }
internal double CurrentWidth { get; set; } = double.NaN;

/// <summary>
/// Gets or sets the internal copy of the <see cref="DesiredWidth"/> property to be used in calculations, this gets manipulated in Auto-Size mode.
/// Gets the internal calculated or manually set width of this column, as a positive value.
/// </summary>
internal GridLength CurrentWidth { get; private set; }
internal double ActualCurrentWidth => double.IsNaN(CurrentWidth) ? 0 : Math.Abs(CurrentWidth);

internal bool IsAbsolute => DesiredWidth.IsAbsolute;

internal bool IsAuto => DesiredWidth.IsAuto;

internal bool IsAutoFit => DesiredWidth.IsAuto && !(CurrentWidth > 0);

internal bool IsStar => DesiredWidth.IsStar;

internal bool IsStarProportion => DesiredWidth.IsStar && !(CurrentWidth > 0);

/// <summary>
/// Gets or sets whether the column can be resized by the user.
Expand All @@ -36,10 +52,13 @@ public bool CanResize
/// Identifies the <see cref="CanResize"/> property.
/// </summary>
public static readonly DependencyProperty CanResizeProperty =
DependencyProperty.Register("CanResize", typeof(bool), typeof(DataColumn), new PropertyMetadata(false));
DependencyProperty.Register(
nameof(CanResize), typeof(bool), typeof(DataColumn),
new PropertyMetadata(false));

/// <summary>
/// Gets or sets the desired width of the column upon initialization. Defaults to a <see cref="GridLength"/> of 1 <see cref="GridUnitType.Star"/>.
/// Gets or sets the desired width of the column upon initialization. Defaults to a <see cref="GridLength"/>
/// of 1 <see cref="GridUnitType.Star"/>.
/// </summary>
public GridLength DesiredWidth
{
Expand All @@ -51,22 +70,34 @@ public GridLength DesiredWidth
/// Identifies the <see cref="DesiredWidth"/> property.
/// </summary>
public static readonly DependencyProperty DesiredWidthProperty =
DependencyProperty.Register(nameof(DesiredWidth), typeof(GridLength), typeof(DataColumn), new PropertyMetadata(GridLength.Auto, DesiredWidth_PropertyChanged));
DependencyProperty.Register(
nameof(DesiredWidth), typeof(GridLength), typeof(DataColumn),
new PropertyMetadata(GridLength.Auto, DesiredWidth_PropertyChanged));

private static void DesiredWidth_PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
// If the developer updates the size of the column, update our internal copy
if (d is DataColumn col)
// If the developer updates the size of the column, update our internal value.
if (d is DataColumn column)
{
col.CurrentWidth = col.DesiredWidth;
if (column.DesiredWidth is { GridUnitType: GridUnitType.Pixel, Value: var value })
{
column.CurrentWidth = value;
}

// Request to measure for the IsAutoFit or IsStarProportion columns.
column.DataTable?.InvalidateMeasure();
}
}

/// <summary>
/// Constructor.
/// </summary>
public DataColumn()
{
this.DefaultStyleKey = typeof(DataColumn);
}

/// <inheritdoc/>
protected override void OnApplyTemplate()
{
if (PART_ColumnSizer != null)
Expand Down Expand Up @@ -108,13 +139,12 @@ private void PART_ColumnSizer_ManipulationCompleted(object sender, ManipulationC
private void ColumnResizedByUserSizer()
{
// Update our internal representation to be our size now as a fixed value.
CurrentWidth = new(this.ActualWidth);

// Notify the rest of the table to update
if (_parent?.TryGetTarget(out DataTable? parent) == true
&& parent != null)
if (CurrentWidth != this.ActualWidth)
{
parent.ColumnResized();
CurrentWidth = this.ActualWidth;

// Notify the rest of the table to update
DataTable?.ColumnResized();
}
}
}
79 changes: 39 additions & 40 deletions components/DataTable/src/DataTable/DataColumn.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,45 +12,44 @@

<Style x:Key="DefaultDataColumnStyle"
TargetType="controls:DataColumn">
<Style.Setters>
<!-- TODO: This is going to be different between ListView and HeaderedItemsControl, how do we want to handle? -->
<Setter Property="Padding" Value="4,0" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="Foreground" Value="{ThemeResource TextFillColorSecondaryBrush}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="controls:DataColumn">
<Grid Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{TemplateBinding CornerRadius}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<ContentPresenter Margin="{TemplateBinding Padding}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Foreground="{TemplateBinding Foreground}" />
<controls:ContentSizer x:Name="PART_ColumnSizer"
Grid.Column="1"
Width="8"
MinWidth="4"
Margin="0"
Padding="0"
Background="Transparent"
Foreground="{ThemeResource ControlStrokeColorSecondaryBrush}"
Visibility="{Binding CanResize, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource DataColumnBoolToVisibilityConverter}}">
<controls:ContentSizer.Resources>
<x:Double x:Key="SizerBaseThumbWidth">2</x:Double>
<x:Double x:Key="SizerBaseThumbHeight">16</x:Double>
</controls:ContentSizer.Resources>
</controls:ContentSizer>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style.Setters>
<!-- TODO: This is going to be different between ListView and HeaderedItemsControl, how do we want to handle? -->
<Setter Property="Padding" Value="4,0" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="Foreground" Value="{ThemeResource TextFillColorSecondaryBrush}" />
<Setter Property="IsTabStop" Value="False" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="controls:DataColumn">
<Grid Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{TemplateBinding CornerRadius}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<ContentPresenter Margin="{TemplateBinding Padding}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Foreground="{TemplateBinding Foreground}" />
<controls:ContentSizer x:Name="PART_ColumnSizer"
Grid.Column="1"
Width="8"
MinWidth="4"
Margin="0"
Padding="0"
Background="Transparent"
Foreground="{ThemeResource ControlStrokeColorSecondaryBrush}"
Visibility="{Binding CanResize, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource DataColumnBoolToVisibilityConverter}}">
<controls:ContentSizer.Resources>
<x:Double x:Key="SizerBaseThumbWidth">2</x:Double>
<x:Double x:Key="SizerBaseThumbHeight">16</x:Double>
</controls:ContentSizer.Resources>
</controls:ContentSizer>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
Loading