Removing Sizers
This commit is contained in:
Родитель
0d2446a269
Коммит
1761f828e0
|
@ -1,3 +0,0 @@
|
|||
@ECHO OFF
|
||||
|
||||
powershell ..\..\tooling\ProjectHeads\GenerateSingleSampleHeads.ps1 -componentPath %CD% %*
|
Двоичные данные
components/SizerBase/samples/Assets/ContentSizer.png
Двоичные данные
components/SizerBase/samples/Assets/ContentSizer.png
Двоичный файл не отображается.
До Ширина: | Высота: | Размер: 1.9 KiB |
Двоичные данные
components/SizerBase/samples/Assets/GridSplitter.png
Двоичные данные
components/SizerBase/samples/Assets/GridSplitter.png
Двоичный файл не отображается.
До Ширина: | Высота: | Размер: 2.6 KiB |
Двоичные данные
components/SizerBase/samples/Assets/PropertySizer.png
Двоичные данные
components/SizerBase/samples/Assets/PropertySizer.png
Двоичный файл не отображается.
До Ширина: | Высота: | Размер: 1.9 KiB |
Двоичные данные
components/SizerBase/samples/Assets/Sizers.png
Двоичные данные
components/SizerBase/samples/Assets/Sizers.png
Двоичный файл не отображается.
До Ширина: | Высота: | Размер: 2.9 KiB |
|
@ -1,25 +0,0 @@
|
|||
---
|
||||
title: ContentSizer
|
||||
author: mhawker
|
||||
description: The ContentSizer is a control which can be used to resize any element, usually its parent.
|
||||
keywords: ContentSizer, SizerBase, Control, Layout, Expander, Splitter
|
||||
dev_langs:
|
||||
- csharp
|
||||
category: Controls
|
||||
subcategory: Layout
|
||||
discussion-id: 96
|
||||
issue-id: 101
|
||||
icon: Assets/ContentSizer.png
|
||||
---
|
||||
|
||||
**If you are using a `Grid`, use [GridSplitter](GridSplitter.md) instead.**
|
||||
|
||||
The main use-case for a ContentSizer is to create an expandable shelf for your application. This allows the `Expander` itself to remember its opening/closing sizes.
|
||||
|
||||
A GridSplitter would be insufficient as it would force the grid to remember the row size and maintain its position when the `Expander` collapses.
|
||||
|
||||
> [!SAMPLE ContentSizerTopShelfPage]
|
||||
|
||||
The following example shows how to use the ContentSizer to create a left-side shelf; however, this scenario can also be accomplished with a `GridSplitter`.
|
||||
|
||||
> [!SAMPLE ContentSizerLeftShelfPage]
|
|
@ -1,32 +0,0 @@
|
|||
<!-- Licensed to the .NET Foundation under one or more agreements. The .NET Foundation licenses this file to you under the MIT license. See the LICENSE file in the project root for more information. -->
|
||||
<Page x:Class="SizerBaseExperiment.Samples.ContentSizerLeftShelfPage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="using:CommunityToolkit.Labs.WinUI"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Grid MinWidth="400"
|
||||
MinHeight="300">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- Left-side 'Shelf', In this case you could also use a GridSplitter -->
|
||||
<Border x:Name="SideContent"
|
||||
MinWidth="200"
|
||||
MaxWidth="600"
|
||||
Background="{ThemeResource AccentFillColorDefaultBrush}">
|
||||
<TextBlock HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{ThemeResource TextOnAccentFillColorPrimaryBrush}"
|
||||
Style="{ThemeResource BodyStrongTextBlockStyle}"
|
||||
Text="Side Content" />
|
||||
</Border>
|
||||
<controls:ContentSizer Grid.Column="1"
|
||||
TargetControl="{x:Bind SideContent}" />
|
||||
</Grid>
|
||||
</Page>
|
|
@ -1,14 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace SizerBaseExperiment.Samples;
|
||||
|
||||
[ToolkitSample(id: nameof(ContentSizerLeftShelfPage), "Left-side Shelf", description: "Shows how to create an expandable shelf on the left-side of your app.")]
|
||||
public sealed partial class ContentSizerLeftShelfPage : Page
|
||||
{
|
||||
public ContentSizerLeftShelfPage()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
<!-- Licensed to the .NET Foundation under one or more agreements. The .NET Foundation licenses this file to you under the MIT license. See the LICENSE file in the project root for more information. -->
|
||||
<Page x:Class="SizerBaseExperiment.Samples.ContentSizerTopShelfPage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="using:CommunityToolkit.Labs.WinUI"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Grid MinHeight="300">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- Bottom 'Shelf', In this case you cannot use GridSplitter as row would maintain its size when Expander gets collapsed -->
|
||||
<muxc:Expander x:Name="TopExpander"
|
||||
VerticalAlignment="Top"
|
||||
HorizontalContentAlignment="Stretch"
|
||||
ExpandDirection="Up"
|
||||
Header="This is some Shelf"
|
||||
IsExpanded="True">
|
||||
<Grid x:Name="ExpandContent"
|
||||
Height="128"
|
||||
MinHeight="32"
|
||||
MaxHeight="256">
|
||||
<TextBlock HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Text="This is the expanded content"
|
||||
TextWrapping="Wrap" />
|
||||
</Grid>
|
||||
</muxc:Expander>
|
||||
<!-- We expand the inner content size here so that Expander maintains it's size properly. -->
|
||||
<controls:ContentSizer Grid.Row="1"
|
||||
Height="16"
|
||||
VerticalAlignment="Top"
|
||||
Orientation="Horizontal"
|
||||
TargetControl="{x:Bind ExpandContent}"
|
||||
Visibility="{x:Bind TopExpander.IsExpanded, Mode=OneWay}" />
|
||||
</Grid>
|
||||
</Page>
|
|
@ -1,14 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace SizerBaseExperiment.Samples;
|
||||
|
||||
[ToolkitSample(id: nameof(ContentSizerTopShelfPage), "Top Shelf", description: "Shows how to create an expandable shelf on the top of your app.")]
|
||||
public sealed partial class ContentSizerTopShelfPage : Page
|
||||
{
|
||||
public ContentSizerTopShelfPage()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
<!--
|
||||
WinUI 2 under UWP uses TargetFramework uap10.0.*
|
||||
WinUI 3 under WinAppSdk uses TargetFramework net6.0-windows10.*
|
||||
However, under Uno-powered platforms, both WinUI 2 and 3 can share the same TargetFramework.
|
||||
|
||||
MSBuild doesn't play nicely with this out of the box, so we've made it easy for you.
|
||||
|
||||
For .NET Standard packages, you can use the Nuget Package Manager in Visual Studio.
|
||||
For UWP / WinAppSDK / Uno packages, place the package references here.
|
||||
-->
|
||||
<Project>
|
||||
<!-- WinUI 2 / UWP -->
|
||||
<ItemGroup Condition="'$(IsUwp)' == 'true'">
|
||||
<!-- <PackageReference Include="Microsoft.Toolkit.Uwp.UI.Controls.Primitives" Version="7.1.2"/> -->
|
||||
</ItemGroup>
|
||||
|
||||
<!-- WinUI 2 / Uno -->
|
||||
<ItemGroup Condition="'$(IsUno)' == 'true' AND '$(WinUIMajorVersion)' == '2'">
|
||||
<!-- <PackageReference Include="Uno.Microsoft.Toolkit.Uwp.UI.Controls.Primitives" Version="7.1.11"/> -->
|
||||
</ItemGroup>
|
||||
|
||||
<!-- WinUI 3 / WinAppSdk -->
|
||||
<ItemGroup Condition="'$(IsWinAppSdk)' == 'true'">
|
||||
<!-- <PackageReference Include="CommunityToolkit.WinUI.UI.Controls.Primitives" Version="7.1.2"/> -->
|
||||
</ItemGroup>
|
||||
|
||||
<!-- WinUI 3 / Uno -->
|
||||
<ItemGroup Condition="'$(IsUno)' == 'true' AND '$(WinUIMajorVersion)' == '3'">
|
||||
<!-- <PackageReference Include="Uno.CommunityToolkit.WinUI.UI.Controls.Primitives" Version="7.1.100-dev.15.g12261e2626"/> -->
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -1,20 +0,0 @@
|
|||
---
|
||||
title: GridSplitter
|
||||
author: mhawker
|
||||
description: The GridSplitter control provides an easy-to-use Splitter that redistributes space between columns or rows of a Grid Control.
|
||||
keywords: ContentSizer, SizerBase, Control, Layout, Expander
|
||||
dev_langs:
|
||||
- csharp
|
||||
category: Controls
|
||||
subcategory: Layout
|
||||
discussion-id: 96
|
||||
issue-id: 101
|
||||
icon: Assets/GridSplitter.png
|
||||
---
|
||||
|
||||
The control automatically detects the targeted columns/rows to resize, while dragging the control it starts to resize the columns/rows and redistributes space between columns/rows,
|
||||
you can manually specify the `ResizeDirection` (`Auto` / `Column` / `Row`) and the `ResizeBehavior` to select which columns/rows to resize.
|
||||
|
||||
`GridSplitter` control will resize the targeted rows or columns
|
||||
|
||||
> [!SAMPLE GridSplitterPage]
|
|
@ -1,106 +0,0 @@
|
|||
<Page x:Class="SizerBaseExperiment.Samples.GridSplitterPage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="using:CommunityToolkit.Labs.WinUI"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Page.Resources>
|
||||
<Style TargetType="Border">
|
||||
<Setter Property="BorderThickness" Value="1,1,0,0" />
|
||||
<Setter Property="Padding" Value="16" />
|
||||
<Setter Property="BorderBrush" Value="{ThemeResource SystemControlHighlightChromeHighBrush}" />
|
||||
</Style>
|
||||
|
||||
<Style TargetType="TextBlock">
|
||||
<Setter Property="TextWrapping" Value="Wrap" />
|
||||
</Style>
|
||||
</Page.Resources>
|
||||
|
||||
<Grid x:Name="RootGrid"
|
||||
Height="300"
|
||||
VerticalAlignment="Top"
|
||||
BorderBrush="{ThemeResource SystemControlHighlightChromeHighBrush}"
|
||||
BorderThickness="0,0,1,1">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition MinHeight="100"
|
||||
MaxHeight="300" />
|
||||
<RowDefinition Height="200" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition MinWidth="100"
|
||||
MaxWidth="300" />
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup>
|
||||
<VisualState x:Name="Full">
|
||||
<VisualState.StateTriggers>
|
||||
<AdaptiveTrigger MinWindowWidth="600" />
|
||||
</VisualState.StateTriggers>
|
||||
</VisualState>
|
||||
<VisualState x:Name="Small">
|
||||
<VisualState.StateTriggers>
|
||||
<AdaptiveTrigger MinWindowWidth="0" />
|
||||
</VisualState.StateTriggers>
|
||||
|
||||
<VisualState.Setters>
|
||||
<Setter Target="RootGrid.Padding" Value="12" />
|
||||
<Setter Target="RootGrid.FontSize" Value="12" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
|
||||
<Border Grid.Row="0"
|
||||
Grid.Column="0">
|
||||
<TextBlock Text="This text to simulate the resizing feature of the Grid Splitter Control, try to move the splitter to see the effect RowDefinition MinHeight='100'" />
|
||||
</Border>
|
||||
<Border Grid.Row="0"
|
||||
Grid.Column="1">
|
||||
<TextBlock Text="This text to simulate the resizing feature of the Grid Splitter Control, try to move the splitter to see the effect" />
|
||||
</Border>
|
||||
<Border Grid.Row="0"
|
||||
Grid.Column="2">
|
||||
<TextBlock Text="This text to simulate the resizing feature of the Grid Splitter Control, try to move the splitter to see the effect" />
|
||||
</Border>
|
||||
|
||||
<Border Grid.Row="1"
|
||||
Grid.Column="0">
|
||||
<TextBlock Text="This text to simulate the resizing feature of the Grid Splitter Control, try to move the splitter to see the effect" />
|
||||
</Border>
|
||||
<Border Grid.Row="1"
|
||||
Grid.Column="1">
|
||||
<TextBlock Text="This text to simulate the resizing feature of the Grid Splitter Control, try to move the splitter to see the effect" />
|
||||
</Border>
|
||||
<Border Grid.Row="1"
|
||||
Grid.Column="2">
|
||||
<TextBlock Text="This text to simulate the resizing feature of the Grid Splitter Control, try to move the splitter to see the effect" />
|
||||
</Border>
|
||||
|
||||
<!-- Column Grid Splitter -->
|
||||
<controls:GridSplitter Grid.Column="1"
|
||||
Width="16"
|
||||
HorizontalAlignment="Left"
|
||||
ResizeBehavior="BasedOnAlignment"
|
||||
ResizeDirection="Auto">
|
||||
<controls:GridSplitter.RenderTransform>
|
||||
<TranslateTransform X="-8" />
|
||||
</controls:GridSplitter.RenderTransform>
|
||||
</controls:GridSplitter>
|
||||
|
||||
<!-- Row Grid Splitter -->
|
||||
<controls:GridSplitter Grid.Row="1"
|
||||
Grid.ColumnSpan="3"
|
||||
Height="16"
|
||||
VerticalAlignment="Top">
|
||||
<controls:GridSplitter.RenderTransform>
|
||||
<TranslateTransform Y="-8" />
|
||||
</controls:GridSplitter.RenderTransform>
|
||||
</controls:GridSplitter>
|
||||
</Grid>
|
||||
</Page>
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace SizerBaseExperiment.Samples;
|
||||
|
||||
/// <summary>
|
||||
/// An empty page that can be used on its own or navigated to within a Frame.
|
||||
/// </summary>
|
||||
[ToolkitSample(id: nameof(GridSplitterPage), "GridSplitter Example", description: "Splitter that redistributes space between columns or rows of a Grid Control")]
|
||||
public sealed partial class GridSplitterPage : Page
|
||||
{
|
||||
public GridSplitterPage()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
---
|
||||
title: PropertySizer
|
||||
author: mhawker
|
||||
description: The PropertySizer is a control which can be used to manipulate the value of another double based property.
|
||||
keywords: PropertySizer, SizerBase, Control, Layout, NavigationView, Splitter
|
||||
dev_langs:
|
||||
- csharp
|
||||
category: Controls
|
||||
subcategory: Layout
|
||||
discussion-id: 96
|
||||
issue-id: 101
|
||||
icon: Assets/PropertySizer.png
|
||||
---
|
||||
|
||||
**If you are using a `Grid`, use `GridSplitter` instead.**
|
||||
|
||||
## Examples
|
||||
|
||||
The main use-case is for `PropertySizer` to allow you to manipulate the `OpenPaneLength` property of a `NavigationView` control to create a user customizable size shelf. This is handy when using `NavigationView` with a tree of items that represents some project or folder structure for your application.
|
||||
|
||||
Both `GridSplitter` and `ContentSizer` are insufficient as they would force the `NavigationView` to a specific size and not allow it to remember its size when it expands or collapses.
|
||||
|
||||
> [!SAMPLE PropertySizerNavigationViewPage]
|
|
@ -1,72 +0,0 @@
|
|||
<!-- Licensed to the .NET Foundation under one or more agreements. The .NET Foundation licenses this file to you under the MIT license. See the LICENSE file in the project root for more information. -->
|
||||
<Page x:Class="SizerBaseExperiment.Samples.PropertySizerNavigationViewPage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="using:CommunityToolkit.Labs.WinUI"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<muxc:NavigationView x:Name="ViewPanel"
|
||||
Width="500"
|
||||
MinHeight="300"
|
||||
HorizontalAlignment="Left"
|
||||
IsPaneOpen="True"
|
||||
OpenPaneLength="300"
|
||||
PaneDisplayMode="Left">
|
||||
<muxc:NavigationView.AutoSuggestBox>
|
||||
<AutoSuggestBox AutomationProperties.Name="Search"
|
||||
QueryIcon="Find" />
|
||||
</muxc:NavigationView.AutoSuggestBox>
|
||||
<muxc:NavigationView.MenuItems>
|
||||
<muxc:NavigationViewItem Content="Menu Item1"
|
||||
Tag="SamplePage1">
|
||||
<muxc:NavigationViewItem.Icon>
|
||||
<SymbolIcon Symbol="Play" />
|
||||
</muxc:NavigationViewItem.Icon>
|
||||
</muxc:NavigationViewItem>
|
||||
<muxc:NavigationViewItem Content="Menu Item2"
|
||||
Tag="SamplePage2">
|
||||
<muxc:NavigationViewItem.Icon>
|
||||
<SymbolIcon Symbol="Save" />
|
||||
</muxc:NavigationViewItem.Icon>
|
||||
</muxc:NavigationViewItem>
|
||||
<muxc:NavigationViewItem Content="Menu Item3 with Really Long Name and Such..."
|
||||
Tag="SamplePage3">
|
||||
<muxc:NavigationViewItem.Icon>
|
||||
<SymbolIcon Symbol="Refresh" />
|
||||
</muxc:NavigationViewItem.Icon>
|
||||
</muxc:NavigationViewItem>
|
||||
<muxc:NavigationViewItem Content="Menu Item4"
|
||||
Tag="SamplePage4">
|
||||
<muxc:NavigationViewItem.Icon>
|
||||
<SymbolIcon Symbol="Download" />
|
||||
</muxc:NavigationViewItem.Icon>
|
||||
</muxc:NavigationViewItem>
|
||||
</muxc:NavigationView.MenuItems>
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<!-- Note the use of a TwoWay binding here, this is required for this control to work. -->
|
||||
<controls:PropertySizer HorizontalAlignment="Left"
|
||||
Binding="{x:Bind ViewPanel.OpenPaneLength, Mode=TwoWay}"
|
||||
Maximum="440"
|
||||
Minimum="52"
|
||||
Visibility="{x:Bind ViewPanel.IsPaneOpen, Mode=OneWay}" />
|
||||
<!--In An Application, put your host frame here: <Frame Grid.Column="1"/>-->
|
||||
<!-- Here we show the content as a border for a visual aid -->
|
||||
<Border Grid.Column="1"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
Background="{ThemeResource AccentFillColorDefaultBrush}">
|
||||
<TextBlock HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{ThemeResource TextOnAccentFillColorPrimaryBrush}"
|
||||
Text="{x:Bind ViewPanel.OpenPaneLength, Mode=OneWay}" />
|
||||
</Border>
|
||||
</Grid>
|
||||
</muxc:NavigationView>
|
||||
</Page>
|
|
@ -1,14 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace SizerBaseExperiment.Samples;
|
||||
|
||||
[ToolkitSample(id: nameof(PropertySizerNavigationViewPage), "NavigationView Shelf", description: "Shows how to create an expandable shelf using a NavigationView and PropertySizer.")]
|
||||
public sealed partial class PropertySizerNavigationViewPage : Page
|
||||
{
|
||||
public PropertySizerNavigationViewPage()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
<Project Sdk="MSBuild.Sdk.Extras/3.0.23">
|
||||
<PropertyGroup>
|
||||
<ToolkitComponentName>SizerBase</ToolkitComponentName>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Sets this up as a toolkit component's sample project -->
|
||||
<Import Project="$(ToolingDirectory)\ToolkitComponent.SampleProject.props" />
|
||||
</Project>
|
|
@ -1,29 +0,0 @@
|
|||
---
|
||||
title: Sizer Controls
|
||||
author: mhawker
|
||||
description: The Sizer controls allow users to resize various parts of your UI easily in a consistent fashion.
|
||||
keywords: GridSplitter, ContentSizer, PropertySizer, SizerBase, Control, Layout, Expander, Grid, Splitter
|
||||
dev_langs:
|
||||
- csharp
|
||||
category: Controls
|
||||
subcategory: Layout
|
||||
discussion-id: 96
|
||||
issue-id: 101
|
||||
icon: Assets/Sizers.png
|
||||
---
|
||||
|
||||
The Sizer controls consist of the following:
|
||||
|
||||
- GridSplitter
|
||||
- ContentSizer
|
||||
- PropertySizer
|
||||
|
||||
They each provide an ability for your users to manipulate different parts of your UI experiences.
|
||||
|
||||
This document provides information about common settings you can set on any of these controls.
|
||||
|
||||
## Custom Mouse Cursor
|
||||
|
||||
You may want to change the cursor that is shown when hovering over your element like this:
|
||||
|
||||
> [!SAMPLE SizerCursorPage]
|
|
@ -1,26 +0,0 @@
|
|||
<!-- Licensed to the .NET Foundation under one or more agreements. The .NET Foundation licenses this file to you under the MIT license. See the LICENSE file in the project root for more information. -->
|
||||
<Page x:Class="SizerBaseExperiment.Samples.SizerCursorPage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="using:CommunityToolkit.Labs.WinUI"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Grid MinWidth="400"
|
||||
MinHeight="300">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Border x:Name="SomeContent"
|
||||
MinWidth="200"
|
||||
MaxWidth="600"
|
||||
Background="{ThemeResource AccentFillColorDefaultBrush}" />
|
||||
<controls:ContentSizer Grid.Column="1"
|
||||
Cursor="Hand"
|
||||
TargetControl="{x:Bind SomeContent}" />
|
||||
</Grid>
|
||||
</Page>
|
|
@ -1,14 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace SizerBaseExperiment.Samples;
|
||||
|
||||
[ToolkitSample(id: nameof(SizerCursorPage), "Custom Mouse Cursor", description: "Shows how to change the cursor of a Sizer control.")]
|
||||
public sealed partial class SizerCursorPage : Page
|
||||
{
|
||||
public SizerCursorPage()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
// These `InternalsVisibleTo` calls are intended to make it easier for
|
||||
// for any internal code to be testable in all the different test projects
|
||||
// used with the Labs infrastructure.
|
||||
[assembly: InternalsVisibleTo("SizerBase.Tests.Uwp")]
|
||||
[assembly: InternalsVisibleTo("SizerBase.Tests.WinAppSdk")]
|
||||
[assembly: InternalsVisibleTo("CommunityToolkit.Tests.Uwp")]
|
||||
[assembly: InternalsVisibleTo("CommunityToolkit.Tests.WinAppSdk")]
|
|
@ -1,13 +0,0 @@
|
|||
<Project Sdk="MSBuild.Sdk.Extras/3.0.23">
|
||||
<PropertyGroup>
|
||||
<ToolkitComponentName>SizerBase</ToolkitComponentName>
|
||||
<Description>This package contains SizerBase.</Description>
|
||||
<Version>0.0.4</Version>
|
||||
|
||||
<!-- Rns suffix is required for namespaces shared across projects. See https://github.com/CommunityToolkit/Labs-Windows/issues/152 -->
|
||||
<RootNamespace>CommunityToolkit.Labs.WinUI.SizerBaseRns</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Sets this up as a toolkit component's source project -->
|
||||
<Import Project="$(ToolingDirectory)\ToolkitComponent.SourceProject.props" />
|
||||
</Project>
|
|
@ -1,74 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using CommunityToolkit.Labs.WinUI.SizerBaseLocal;
|
||||
|
||||
namespace CommunityToolkit.Labs.WinUI;
|
||||
|
||||
// Events for ContentSizer.
|
||||
public partial class ContentSizer
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
protected override void OnLoaded(RoutedEventArgs e)
|
||||
{
|
||||
if (TargetControl == null)
|
||||
{
|
||||
TargetControl = this.FindAscendant<FrameworkElement>();
|
||||
}
|
||||
}
|
||||
|
||||
private double _currentSize;
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void OnDragStarting()
|
||||
{
|
||||
if (TargetControl != null)
|
||||
{
|
||||
_currentSize =
|
||||
Orientation == Orientation.Vertical ?
|
||||
TargetControl.ActualWidth :
|
||||
TargetControl.ActualHeight;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override bool OnDragHorizontal(double horizontalChange)
|
||||
{
|
||||
if (TargetControl == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
horizontalChange = IsDragInverted ? -horizontalChange : horizontalChange;
|
||||
|
||||
if (!IsValidWidth(TargetControl, _currentSize + horizontalChange, ActualWidth))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
TargetControl.Width = _currentSize + horizontalChange;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override bool OnDragVertical(double verticalChange)
|
||||
{
|
||||
if (TargetControl == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
verticalChange = IsDragInverted ? -verticalChange : verticalChange;
|
||||
|
||||
if (!IsValidHeight(TargetControl, _currentSize + verticalChange, ActualHeight))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
TargetControl.Height = _currentSize + verticalChange;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -1,62 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace CommunityToolkit.Labs.WinUI;
|
||||
|
||||
// Properties for ContentSizer.
|
||||
public partial class ContentSizer
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the <see cref="ContentSizer"/> control is resizing in the opposite direction.
|
||||
/// </summary>
|
||||
public bool IsDragInverted
|
||||
{
|
||||
get { return (bool)GetValue(IsDragInvertedProperty); }
|
||||
set { SetValue(IsDragInvertedProperty, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Identifies the <see cref="IsDragInverted"/> dependency property.
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty IsDragInvertedProperty =
|
||||
DependencyProperty.Register(nameof(IsDragInverted), typeof(bool), typeof(ContentSizer), new PropertyMetadata(false));
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the control that the <see cref="ContentSizer"/> is resizing. Be default, this will be the visual ancestor of the <see cref="ContentSizer"/>.
|
||||
/// </summary>
|
||||
public FrameworkElement? TargetControl
|
||||
{
|
||||
get { return (FrameworkElement?)GetValue(TargetControlProperty); }
|
||||
set { SetValue(TargetControlProperty, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Identifies the <see cref="TargetControl"/> dependency property.
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty TargetControlProperty =
|
||||
DependencyProperty.Register(nameof(TargetControl), typeof(FrameworkElement), typeof(ContentSizer), new PropertyMetadata(null, OnTargetControlChanged));
|
||||
|
||||
private static void OnTargetControlChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
// TODO: Should we do this after the TargetControl is Loaded? (And use ActualWidth?)
|
||||
// Or should we just do it in the manipulation event if Width is null?
|
||||
|
||||
// Check if our width can be manipulated
|
||||
if (d is SizerBase splitterBase && e.NewValue is FrameworkElement element)
|
||||
{
|
||||
// TODO: For Auto ResizeDirection we might want to do detection logic (TBD) here first?
|
||||
if (splitterBase.Orientation != Orientation.Horizontal && double.IsNaN(element.Width))
|
||||
{
|
||||
// We need to set the Width or Height somewhere,
|
||||
// as if it's NaN we won't be able to manipulate it.
|
||||
element.Width = element.DesiredSize.Width;
|
||||
}
|
||||
|
||||
if (splitterBase.Orientation != Orientation.Vertical && double.IsNaN(element.Height))
|
||||
{
|
||||
element.Height = element.DesiredSize.Height;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace CommunityToolkit.Labs.WinUI;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="ContentSizer"/> is a control which can be used to resize any element, usually its parent. If you are using a <see cref="Grid"/>, use <see cref="GridSplitter"/> instead.
|
||||
/// </summary>
|
||||
public partial class ContentSizer : SizerBase
|
||||
{
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
<!--
|
||||
WinUI 2 under UWP uses TargetFramework uap10.0.*
|
||||
WinUI 3 under WinAppSdk uses TargetFramework net6.0-windows10.*
|
||||
However, under Uno-powered platforms, both WinUI 2 and 3 can share the same TargetFramework.
|
||||
|
||||
MSBuild doesn't play nicely with this out of the box, so we've made it easy for you.
|
||||
|
||||
For .NET Standard packages, you can use the Nuget Package Manager in Visual Studio.
|
||||
For UWP / WinAppSDK / Uno packages, place the package references here.
|
||||
-->
|
||||
<Project>
|
||||
<!-- WinUI 2 / UWP -->
|
||||
<ItemGroup Condition="'$(IsUwp)' == 'true'">
|
||||
<!-- <PackageReference Include="Microsoft.Toolkit.Uwp.UI.Controls.Primitives" Version="7.1.2"/> -->
|
||||
</ItemGroup>
|
||||
|
||||
<!-- WinUI 2 / Uno -->
|
||||
<ItemGroup Condition="'$(IsUno)' == 'true' AND '$(WinUIMajorVersion)' == '2'">
|
||||
<!-- <PackageReference Include="Uno.Microsoft.Toolkit.Uwp.UI.Controls.Primitives" Version="7.1.11"/> -->
|
||||
</ItemGroup>
|
||||
|
||||
<!-- WinUI 3 / WinAppSdk -->
|
||||
<ItemGroup Condition="'$(IsWinAppSdk)' == 'true'">
|
||||
<!-- <PackageReference Include="CommunityToolkit.WinUI.UI.Controls.Primitives" Version="7.1.2"/> -->
|
||||
</ItemGroup>
|
||||
|
||||
<!-- WinUI 3 / Uno -->
|
||||
<ItemGroup Condition="'$(IsUno)' == 'true' AND '$(WinUIMajorVersion)' == '3'">
|
||||
<!-- <PackageReference Include="Uno.CommunityToolkit.WinUI.UI.Controls.Primitives" Version="7.1.100-dev.15.g12261e2626"/> -->
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -1,56 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace CommunityToolkit.Labs.WinUI;
|
||||
|
||||
public partial class GridSplitter
|
||||
{
|
||||
/// <summary>
|
||||
/// Enum to indicate whether GridSplitter resizes Columns or Rows
|
||||
/// </summary>
|
||||
public enum GridResizeDirection
|
||||
{
|
||||
/// <summary>
|
||||
/// Determines whether to resize rows or columns based on its Alignment and
|
||||
/// width compared to height
|
||||
/// </summary>
|
||||
Auto,
|
||||
|
||||
/// <summary>
|
||||
/// Resize columns when dragging Splitter.
|
||||
/// </summary>
|
||||
Columns,
|
||||
|
||||
/// <summary>
|
||||
/// Resize rows when dragging Splitter.
|
||||
/// </summary>
|
||||
Rows
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enum to indicate what Columns or Rows the GridSplitter resizes
|
||||
/// </summary>
|
||||
public enum GridResizeBehavior
|
||||
{
|
||||
/// <summary>
|
||||
/// Determine which columns or rows to resize based on its Alignment.
|
||||
/// </summary>
|
||||
BasedOnAlignment,
|
||||
|
||||
/// <summary>
|
||||
/// Resize the current and next Columns or Rows.
|
||||
/// </summary>
|
||||
CurrentAndNext,
|
||||
|
||||
/// <summary>
|
||||
/// Resize the previous and current Columns or Rows.
|
||||
/// </summary>
|
||||
PreviousAndCurrent,
|
||||
|
||||
/// <summary>
|
||||
/// Resize the previous and next Columns or Rows.
|
||||
/// </summary>
|
||||
PreviousAndNext
|
||||
}
|
||||
}
|
|
@ -1,169 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace CommunityToolkit.Labs.WinUI;
|
||||
|
||||
public partial class GridSplitter
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
protected override void OnLoaded(RoutedEventArgs e)
|
||||
{
|
||||
_resizeDirection = GetResizeDirection();
|
||||
Orientation = _resizeDirection == GridResizeDirection.Rows ?
|
||||
Orientation.Horizontal : Orientation.Vertical;
|
||||
_resizeBehavior = GetResizeBehavior();
|
||||
}
|
||||
|
||||
private double _currentSize;
|
||||
private double _siblingSize;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void OnDragStarting()
|
||||
{
|
||||
_resizeDirection = GetResizeDirection();
|
||||
Orientation = _resizeDirection == GridResizeDirection.Rows ?
|
||||
Orientation.Horizontal : Orientation.Vertical;
|
||||
_resizeBehavior = GetResizeBehavior();
|
||||
|
||||
// Record starting points
|
||||
if (Orientation == Orientation.Horizontal)
|
||||
{
|
||||
_currentSize = CurrentRow?.ActualHeight ?? -1;
|
||||
_siblingSize = SiblingRow?.ActualHeight ?? -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
_currentSize = CurrentColumn?.ActualWidth ?? -1;
|
||||
_siblingSize = SiblingColumn?.ActualWidth ?? -1;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override bool OnDragVertical(double verticalChange)
|
||||
{
|
||||
if (CurrentRow == null || SiblingRow == null || Resizable == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var currentChange = _currentSize + verticalChange;
|
||||
var siblingChange = _siblingSize + (verticalChange * -1); // sibling moves opposite
|
||||
|
||||
// if current row has fixed height then resize it
|
||||
if (!IsStarRow(CurrentRow))
|
||||
{
|
||||
// No need to check for the row Min height because it is automatically respected
|
||||
return SetRowHeight(CurrentRow, currentChange, GridUnitType.Pixel);
|
||||
}
|
||||
|
||||
// if sibling row has fixed width then resize it
|
||||
else if (!IsStarRow(SiblingRow))
|
||||
{
|
||||
// Would adding to this column make the current column violate the MinWidth?
|
||||
if (IsValidRowHeight(CurrentRow, currentChange) == false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return SetRowHeight(SiblingRow, siblingChange, GridUnitType.Pixel);
|
||||
}
|
||||
|
||||
// if both row haven't fixed height (auto *)
|
||||
else
|
||||
{
|
||||
// change current row height to the new height with respecting the auto
|
||||
// change sibling row height to the new height relative to current row
|
||||
// respect the other star row height by setting it's height to it's actual height with stars
|
||||
|
||||
// We need to validate current and sibling height to not cause any unexpected behavior
|
||||
if (!IsValidRowHeight(CurrentRow, currentChange) ||
|
||||
!IsValidRowHeight(SiblingRow, siblingChange))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach (var rowDefinition in Resizable.RowDefinitions)
|
||||
{
|
||||
if (rowDefinition == CurrentRow)
|
||||
{
|
||||
SetRowHeight(CurrentRow, currentChange, GridUnitType.Star);
|
||||
}
|
||||
else if (rowDefinition == SiblingRow)
|
||||
{
|
||||
SetRowHeight(SiblingRow, siblingChange, GridUnitType.Star);
|
||||
}
|
||||
else if (IsStarRow(rowDefinition))
|
||||
{
|
||||
rowDefinition.Height = new GridLength(rowDefinition.ActualHeight, GridUnitType.Star);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override bool OnDragHorizontal(double horizontalChange)
|
||||
{
|
||||
if (CurrentColumn == null || SiblingColumn == null || Resizable == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var currentChange = _currentSize + horizontalChange;
|
||||
var siblingChange = _siblingSize + (horizontalChange * -1); // sibling moves opposite
|
||||
|
||||
// if current column has fixed width then resize it
|
||||
if (!IsStarColumn(CurrentColumn))
|
||||
{
|
||||
// No need to check for the Column Min width because it is automatically respected
|
||||
return SetColumnWidth(CurrentColumn, currentChange, GridUnitType.Pixel);
|
||||
}
|
||||
|
||||
// if sibling column has fixed width then resize it
|
||||
else if (!IsStarColumn(SiblingColumn))
|
||||
{
|
||||
// Would adding to this column make the current column violate the MinWidth?
|
||||
if (IsValidColumnWidth(CurrentColumn, currentChange) == false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return SetColumnWidth(SiblingColumn, siblingChange, GridUnitType.Pixel);
|
||||
}
|
||||
|
||||
// if both column haven't fixed width (auto *)
|
||||
else
|
||||
{
|
||||
// change current column width to the new width with respecting the auto
|
||||
// change sibling column width to the new width relative to current column
|
||||
// respect the other star column width by setting it's width to it's actual width with stars
|
||||
|
||||
// We need to validate current and sibling width to not cause any unexpected behavior
|
||||
if (!IsValidColumnWidth(CurrentColumn, currentChange) ||
|
||||
!IsValidColumnWidth(SiblingColumn, siblingChange))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach (var columnDefinition in Resizable.ColumnDefinitions)
|
||||
{
|
||||
if (columnDefinition == CurrentColumn)
|
||||
{
|
||||
SetColumnWidth(CurrentColumn, currentChange, GridUnitType.Star);
|
||||
}
|
||||
else if (columnDefinition == SiblingColumn)
|
||||
{
|
||||
SetColumnWidth(SiblingColumn, siblingChange, GridUnitType.Star);
|
||||
}
|
||||
else if (IsStarColumn(columnDefinition))
|
||||
{
|
||||
columnDefinition.Width = new GridLength(columnDefinition.ActualWidth, GridUnitType.Star);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,245 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace CommunityToolkit.Labs.WinUI;
|
||||
|
||||
public partial class GridSplitter
|
||||
{
|
||||
private static bool IsStarColumn(ColumnDefinition definition)
|
||||
{
|
||||
return ((GridLength)definition.GetValue(ColumnDefinition.WidthProperty)).IsStar;
|
||||
}
|
||||
|
||||
private static bool IsStarRow(RowDefinition definition)
|
||||
{
|
||||
return ((GridLength)definition.GetValue(RowDefinition.HeightProperty)).IsStar;
|
||||
}
|
||||
|
||||
private bool SetColumnWidth(ColumnDefinition columnDefinition, double newWidth, GridUnitType unitType)
|
||||
{
|
||||
var minWidth = columnDefinition.MinWidth;
|
||||
if (!double.IsNaN(minWidth) && newWidth < minWidth)
|
||||
{
|
||||
newWidth = minWidth;
|
||||
}
|
||||
|
||||
var maxWidth = columnDefinition.MaxWidth;
|
||||
if (!double.IsNaN(maxWidth) && newWidth > maxWidth)
|
||||
{
|
||||
newWidth = maxWidth;
|
||||
}
|
||||
|
||||
if (newWidth > ActualWidth)
|
||||
{
|
||||
columnDefinition.Width = new GridLength(newWidth, unitType);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool IsValidColumnWidth(ColumnDefinition columnDefinition, double newWidth)
|
||||
{
|
||||
var minWidth = columnDefinition.MinWidth;
|
||||
if (!double.IsNaN(minWidth) && newWidth < minWidth)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var maxWidth = columnDefinition.MaxWidth;
|
||||
if (!double.IsNaN(maxWidth) && newWidth > maxWidth)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (newWidth <= ActualWidth)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool SetRowHeight(RowDefinition rowDefinition, double newHeight, GridUnitType unitType)
|
||||
{
|
||||
var minHeight = rowDefinition.MinHeight;
|
||||
if (!double.IsNaN(minHeight) && newHeight < minHeight)
|
||||
{
|
||||
newHeight = minHeight;
|
||||
}
|
||||
|
||||
var maxWidth = rowDefinition.MaxHeight;
|
||||
if (!double.IsNaN(maxWidth) && newHeight > maxWidth)
|
||||
{
|
||||
newHeight = maxWidth;
|
||||
}
|
||||
|
||||
if (newHeight > ActualHeight)
|
||||
{
|
||||
rowDefinition.Height = new GridLength(newHeight, unitType);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool IsValidRowHeight(RowDefinition rowDefinition, double newHeight)
|
||||
{
|
||||
var minHeight = rowDefinition.MinHeight;
|
||||
if (!double.IsNaN(minHeight) && newHeight < minHeight)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var maxHeight = rowDefinition.MaxHeight;
|
||||
if (!double.IsNaN(maxHeight) && newHeight > maxHeight)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (newHeight <= ActualHeight)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Return the targeted Column based on the resize behavior
|
||||
private int GetTargetedColumn()
|
||||
{
|
||||
var currentIndex = Grid.GetColumn(TargetControl);
|
||||
return GetTargetIndex(currentIndex);
|
||||
}
|
||||
|
||||
// Return the sibling Row based on the resize behavior
|
||||
private int GetTargetedRow()
|
||||
{
|
||||
var currentIndex = Grid.GetRow(TargetControl);
|
||||
return GetTargetIndex(currentIndex);
|
||||
}
|
||||
|
||||
// Return the sibling Column based on the resize behavior
|
||||
private int GetSiblingColumn()
|
||||
{
|
||||
var currentIndex = Grid.GetColumn(TargetControl);
|
||||
return GetSiblingIndex(currentIndex);
|
||||
}
|
||||
|
||||
// Return the sibling Row based on the resize behavior
|
||||
private int GetSiblingRow()
|
||||
{
|
||||
var currentIndex = Grid.GetRow(TargetControl);
|
||||
return GetSiblingIndex(currentIndex);
|
||||
}
|
||||
|
||||
// Gets index based on resize behavior for first targeted row/column
|
||||
private int GetTargetIndex(int currentIndex)
|
||||
{
|
||||
switch (_resizeBehavior)
|
||||
{
|
||||
case GridResizeBehavior.CurrentAndNext:
|
||||
return currentIndex;
|
||||
case GridResizeBehavior.PreviousAndNext:
|
||||
return currentIndex - 1;
|
||||
case GridResizeBehavior.PreviousAndCurrent:
|
||||
return currentIndex - 1;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// Gets index based on resize behavior for second targeted row/column
|
||||
private int GetSiblingIndex(int currentIndex)
|
||||
{
|
||||
switch (_resizeBehavior)
|
||||
{
|
||||
case GridResizeBehavior.CurrentAndNext:
|
||||
return currentIndex + 1;
|
||||
case GridResizeBehavior.PreviousAndNext:
|
||||
return currentIndex + 1;
|
||||
case GridResizeBehavior.PreviousAndCurrent:
|
||||
return currentIndex;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// Checks the control alignment and Width/Height to detect the control resize direction columns/rows
|
||||
private GridResizeDirection GetResizeDirection()
|
||||
{
|
||||
GridResizeDirection direction = ResizeDirection;
|
||||
|
||||
if (direction == GridResizeDirection.Auto)
|
||||
{
|
||||
// When HorizontalAlignment is Left, Right or Center, resize Columns
|
||||
if (HorizontalAlignment != HorizontalAlignment.Stretch)
|
||||
{
|
||||
direction = GridResizeDirection.Columns;
|
||||
}
|
||||
|
||||
// When VerticalAlignment is Top, Bottom or Center, resize Rows
|
||||
else if (VerticalAlignment != VerticalAlignment.Stretch)
|
||||
{
|
||||
direction = GridResizeDirection.Rows;
|
||||
}
|
||||
|
||||
// Check Width vs Height
|
||||
else if (ActualWidth <= ActualHeight)
|
||||
{
|
||||
direction = GridResizeDirection.Columns;
|
||||
}
|
||||
else
|
||||
{
|
||||
direction = GridResizeDirection.Rows;
|
||||
}
|
||||
}
|
||||
|
||||
return direction;
|
||||
}
|
||||
|
||||
// Get the resize behavior (Which columns/rows should be resized) based on alignment and Direction
|
||||
private GridResizeBehavior GetResizeBehavior()
|
||||
{
|
||||
GridResizeBehavior resizeBehavior = ResizeBehavior;
|
||||
|
||||
if (resizeBehavior == GridResizeBehavior.BasedOnAlignment)
|
||||
{
|
||||
if (_resizeDirection == GridResizeDirection.Columns)
|
||||
{
|
||||
switch (HorizontalAlignment)
|
||||
{
|
||||
case HorizontalAlignment.Left:
|
||||
resizeBehavior = GridResizeBehavior.PreviousAndCurrent;
|
||||
break;
|
||||
case HorizontalAlignment.Right:
|
||||
resizeBehavior = GridResizeBehavior.CurrentAndNext;
|
||||
break;
|
||||
default:
|
||||
resizeBehavior = GridResizeBehavior.PreviousAndNext;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// resize direction is vertical
|
||||
else
|
||||
{
|
||||
switch (VerticalAlignment)
|
||||
{
|
||||
case VerticalAlignment.Top:
|
||||
resizeBehavior = GridResizeBehavior.PreviousAndCurrent;
|
||||
break;
|
||||
case VerticalAlignment.Bottom:
|
||||
resizeBehavior = GridResizeBehavior.CurrentAndNext;
|
||||
break;
|
||||
default:
|
||||
resizeBehavior = GridResizeBehavior.PreviousAndNext;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return resizeBehavior;
|
||||
}
|
||||
}
|
|
@ -1,78 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace CommunityToolkit.Labs.WinUI;
|
||||
|
||||
public partial class GridSplitter
|
||||
{
|
||||
/// <summary>
|
||||
/// Identifies the <see cref="ResizeDirection"/> dependency property.
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty ResizeDirectionProperty
|
||||
= DependencyProperty.Register(
|
||||
nameof(ResizeDirection),
|
||||
typeof(GridResizeDirection),
|
||||
typeof(GridSplitter),
|
||||
new PropertyMetadata(GridResizeDirection.Auto, OnResizeDirectionPropertyChanged));
|
||||
|
||||
private static void OnResizeDirectionPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
if (d is GridSplitter splitter && e.NewValue is GridResizeDirection direction &&
|
||||
direction != GridResizeDirection.Auto)
|
||||
{
|
||||
// Update base classes property based on specific polyfill for GridSplitter
|
||||
splitter.Orientation =
|
||||
direction == GridResizeDirection.Rows ?
|
||||
Orientation.Horizontal :
|
||||
Orientation.Vertical;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Identifies the <see cref="ResizeBehavior"/> dependency property.
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty ResizeBehaviorProperty
|
||||
= DependencyProperty.Register(
|
||||
nameof(ResizeBehavior),
|
||||
typeof(GridResizeBehavior),
|
||||
typeof(GridSplitter),
|
||||
new PropertyMetadata(GridResizeBehavior.BasedOnAlignment));
|
||||
|
||||
/// <summary>
|
||||
/// Identifies the <see cref="ParentLevel"/> dependency property.
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty ParentLevelProperty
|
||||
= DependencyProperty.Register(
|
||||
nameof(ParentLevel),
|
||||
typeof(int),
|
||||
typeof(GridSplitter),
|
||||
new PropertyMetadata(default(int)));
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets whether the Splitter resizes the Columns, Rows, or Both.
|
||||
/// </summary>
|
||||
public GridResizeDirection ResizeDirection
|
||||
{
|
||||
get { return (GridResizeDirection)GetValue(ResizeDirectionProperty); }
|
||||
set { SetValue(ResizeDirectionProperty, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets which Columns or Rows the Splitter resizes.
|
||||
/// </summary>
|
||||
public GridResizeBehavior ResizeBehavior
|
||||
{
|
||||
get { return (GridResizeBehavior)GetValue(ResizeBehaviorProperty); }
|
||||
set { SetValue(ResizeBehaviorProperty, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the level of the parent grid to resize
|
||||
/// </summary>
|
||||
public int ParentLevel
|
||||
{
|
||||
get { return (int)GetValue(ParentLevelProperty); }
|
||||
set { SetValue(ParentLevelProperty, value); }
|
||||
}
|
||||
}
|
|
@ -1,145 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace CommunityToolkit.Labs.WinUI;
|
||||
|
||||
/// <summary>
|
||||
/// Represents the control that redistributes space between columns or rows of a Grid control.
|
||||
/// </summary>
|
||||
public partial class GridSplitter : SizerBase
|
||||
{
|
||||
private GridResizeDirection _resizeDirection;
|
||||
private GridResizeBehavior _resizeBehavior;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the target parent grid from level
|
||||
/// </summary>
|
||||
private FrameworkElement? TargetControl
|
||||
{
|
||||
get
|
||||
{
|
||||
if (ParentLevel == 0)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
// TODO: Can we just use our Visual/Logical Tree extensions for this?
|
||||
var parent = Parent;
|
||||
for (int i = 2; i < ParentLevel; i++) // TODO: Why is this 2? We need better documentation on ParentLevel
|
||||
{
|
||||
if (parent is FrameworkElement frameworkElement)
|
||||
{
|
||||
parent = frameworkElement.Parent;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return parent as FrameworkElement;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets GridSplitter Container Grid
|
||||
/// </summary>
|
||||
private Grid? Resizable => TargetControl?.Parent as Grid;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current Column definition of the parent Grid
|
||||
/// </summary>
|
||||
private ColumnDefinition? CurrentColumn
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Resizable == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var gridSplitterTargetedColumnIndex = GetTargetedColumn();
|
||||
|
||||
if ((gridSplitterTargetedColumnIndex >= 0)
|
||||
&& (gridSplitterTargetedColumnIndex < Resizable.ColumnDefinitions.Count))
|
||||
{
|
||||
return Resizable.ColumnDefinitions[gridSplitterTargetedColumnIndex];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Sibling Column definition of the parent Grid
|
||||
/// </summary>
|
||||
private ColumnDefinition? SiblingColumn
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Resizable == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var gridSplitterSiblingColumnIndex = GetSiblingColumn();
|
||||
|
||||
if ((gridSplitterSiblingColumnIndex >= 0)
|
||||
&& (gridSplitterSiblingColumnIndex < Resizable.ColumnDefinitions.Count))
|
||||
{
|
||||
return Resizable.ColumnDefinitions[gridSplitterSiblingColumnIndex];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current Row definition of the parent Grid
|
||||
/// </summary>
|
||||
private RowDefinition? CurrentRow
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Resizable == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var gridSplitterTargetedRowIndex = GetTargetedRow();
|
||||
|
||||
if ((gridSplitterTargetedRowIndex >= 0)
|
||||
&& (gridSplitterTargetedRowIndex < Resizable.RowDefinitions.Count))
|
||||
{
|
||||
return Resizable.RowDefinitions[gridSplitterTargetedRowIndex];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Sibling Row definition of the parent Grid
|
||||
/// </summary>
|
||||
private RowDefinition? SiblingRow
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Resizable == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var gridSplitterSiblingRowIndex = GetSiblingRow();
|
||||
|
||||
if ((gridSplitterSiblingRowIndex >= 0)
|
||||
&& (gridSplitterSiblingRowIndex < Resizable.RowDefinitions.Count))
|
||||
{
|
||||
return Resizable.RowDefinitions[gridSplitterSiblingRowIndex];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,66 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace CommunityToolkit.Labs.WinUI;
|
||||
|
||||
// Events for PropertySizer.
|
||||
public partial class PropertySizer
|
||||
{
|
||||
private double _currentSize;
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void OnDragStarting()
|
||||
{
|
||||
// We grab the current size of the bound value when we start a drag
|
||||
// and we manipulate from that set point.
|
||||
if (ReadLocalValue(BindingProperty) != DependencyProperty.UnsetValue)
|
||||
{
|
||||
_currentSize = Binding;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override bool OnDragHorizontal(double horizontalChange)
|
||||
{
|
||||
// We use a central function for both horizontal/vertical as
|
||||
// a general property has no notion of direction when we
|
||||
// manipulate it, so the logic is abstracted.
|
||||
return ApplySizeChange(horizontalChange);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override bool OnDragVertical(double verticalChange)
|
||||
{
|
||||
return ApplySizeChange(verticalChange);
|
||||
}
|
||||
|
||||
private bool ApplySizeChange(double newSize)
|
||||
{
|
||||
newSize = IsDragInverted ? -newSize : newSize;
|
||||
|
||||
// We want to be checking the modified final value for bounds checks.
|
||||
newSize += _currentSize;
|
||||
|
||||
// Check if we hit the min/max value, as we should use that if we're on the edge
|
||||
if (ReadLocalValue(MinimumProperty) != DependencyProperty.UnsetValue &&
|
||||
newSize < Minimum)
|
||||
{
|
||||
// We use SetValue here as that'll update our bound property vs. overwriting the binding itself.
|
||||
SetValue(BindingProperty, Minimum);
|
||||
}
|
||||
else if (ReadLocalValue(MaximumProperty) != DependencyProperty.UnsetValue &&
|
||||
newSize > Maximum)
|
||||
{
|
||||
SetValue(BindingProperty, Maximum);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwise, we use the value provided.
|
||||
SetValue(BindingProperty, newSize);
|
||||
}
|
||||
|
||||
// We're always manipulating the value effectively.
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace CommunityToolkit.Labs.WinUI;
|
||||
|
||||
// Properties for PropertySizer.
|
||||
public partial class PropertySizer
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the <see cref="PropertySizer"/> control is resizing in the opposite direction.
|
||||
/// </summary>
|
||||
public bool IsDragInverted
|
||||
{
|
||||
get { return (bool)GetValue(IsDragInvertedProperty); }
|
||||
set { SetValue(IsDragInvertedProperty, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Identifies the <see cref="IsDragInverted"/> dependency property.
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty IsDragInvertedProperty =
|
||||
DependencyProperty.Register(nameof(IsDragInverted), typeof(bool), typeof(PropertySizer), new PropertyMetadata(false));
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a two-way binding to a <c>double</c> value that the <see cref="PropertySizer"/> is manipulating.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Note that the binding should be configured to be a <c>TwoWay</c> binding in order for the control to notify the source of the changed value.
|
||||
/// </remarks>
|
||||
/// <example>
|
||||
/// <controls:PropertySizer Binding="{Binding OpenPaneLength, ElementName=ViewPanel, Mode=TwoWay}">
|
||||
/// </example>
|
||||
public double Binding
|
||||
{
|
||||
get { return (double)GetValue(BindingProperty); }
|
||||
set { SetValue(BindingProperty, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Identifies the <see cref="Binding"/> dependency property.
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty BindingProperty =
|
||||
DependencyProperty.Register(nameof(Binding), typeof(double), typeof(PropertySizer), new PropertyMetadata(null));
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the minimum allowed value for the <see cref="PropertySizer"/> to allow for the <see cref="Binding"/> value. Ignored if not provided.
|
||||
/// </summary>
|
||||
public double Minimum
|
||||
{
|
||||
get { return (double)GetValue(MinimumProperty); }
|
||||
set { SetValue(MinimumProperty, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Identifies the <see cref="Minimum"/> dependency property.
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty MinimumProperty =
|
||||
DependencyProperty.Register(nameof(Minimum), typeof(double), typeof(PropertySizer), new PropertyMetadata(0));
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the maximum allowed value for the <see cref="PropertySizer"/> to allow for the <see cref="Binding"/> value. Ignored if not provided.
|
||||
/// </summary>
|
||||
public double Maximum
|
||||
{
|
||||
get { return (double)GetValue(MaximumProperty); }
|
||||
set { SetValue(MaximumProperty, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Identifies the <see cref="Maximum"/> dependency property.
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty MaximumProperty =
|
||||
DependencyProperty.Register(nameof(Maximum), typeof(double), typeof(PropertySizer), new PropertyMetadata(0));
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace CommunityToolkit.Labs.WinUI;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="PropertySizer"/> is a control which can be used to manipulate the value of another <c>double</c> based property. For instance manipulating the <c>OpenPaneLength</c> of a <c>NavigationView</c> control. If you are using a <see cref="Grid"/>, use <see cref="GridSplitter"/> instead.
|
||||
/// </summary>
|
||||
public partial class PropertySizer : SizerBase
|
||||
{
|
||||
}
|
|
@ -1,72 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace CommunityToolkit.Labs.WinUI.Automation.Peers;
|
||||
|
||||
/// <summary>
|
||||
/// Defines a framework element automation peer for the <see cref="SizerBase"/> controls.
|
||||
/// </summary>
|
||||
public class SizerAutomationPeer : FrameworkElementAutomationPeer
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SizerAutomationPeer"/> class.
|
||||
/// </summary>
|
||||
/// <param name="owner">
|
||||
/// The <see cref="SizerBase" /> that is associated with this <see cref="SizerAutomationPeer" />.
|
||||
/// </param>
|
||||
public SizerAutomationPeer(SizerBase owner)
|
||||
: base(owner)
|
||||
{
|
||||
}
|
||||
|
||||
private SizerBase OwningSizer
|
||||
{
|
||||
get
|
||||
{
|
||||
return (Owner as SizerBase)!;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called by GetClassName that gets a human readable name that, in addition to AutomationControlType,
|
||||
/// differentiates the control represented by this AutomationPeer.
|
||||
/// </summary>
|
||||
/// <returns>The string that contains the name.</returns>
|
||||
protected override string GetClassNameCore()
|
||||
{
|
||||
return Owner.GetType().Name;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called by GetName.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// Returns the first of these that is not null or empty:
|
||||
/// - Value returned by the base implementation
|
||||
/// - Name of the owning ContentSizer
|
||||
/// - ContentSizer class name
|
||||
/// </returns>
|
||||
protected override string GetNameCore()
|
||||
{
|
||||
string name = AutomationProperties.GetName(this.OwningSizer);
|
||||
if (!string.IsNullOrEmpty(name))
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
name = this.OwningSizer.Name;
|
||||
if (!string.IsNullOrEmpty(name))
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
name = base.GetNameCore();
|
||||
if (!string.IsNullOrEmpty(name))
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
|
@ -1,178 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace CommunityToolkit.Labs.WinUI;
|
||||
|
||||
/// <summary>
|
||||
/// Event implementations for <see cref="SizerBase"/>.
|
||||
/// </summary>
|
||||
public partial class SizerBase
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void OnKeyDown(KeyRoutedEventArgs e)
|
||||
{
|
||||
// If we're manipulating with mouse/touch, we ignore keyboard inputs.
|
||||
if (_dragging)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//// TODO: Do we want Ctrl/Shift to be a small increment (kind of inverse to old GridSplitter logic)?
|
||||
//// var ctrl = Window.Current.CoreWindow.GetKeyState(VirtualKey.Control);
|
||||
//// if (ctrl.HasFlag(CoreVirtualKeyStates.Down))
|
||||
//// Note: WPF doesn't do anything here.
|
||||
//// I think if we did anything, we'd create a SmallKeyboardIncrement property?
|
||||
|
||||
// Initialize a drag event for this keyboard interaction.
|
||||
OnDragStarting();
|
||||
|
||||
if (Orientation == Orientation.Vertical)
|
||||
{
|
||||
var horizontalChange = KeyboardIncrement;
|
||||
|
||||
// Important: adjust for RTL language flow settings and invert horizontal axis
|
||||
#if !HAS_UNO
|
||||
if (this.FlowDirection == FlowDirection.RightToLeft)
|
||||
{
|
||||
horizontalChange *= -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (e.Key == Windows.System.VirtualKey.Left)
|
||||
{
|
||||
OnDragHorizontal(-horizontalChange);
|
||||
}
|
||||
else if (e.Key == Windows.System.VirtualKey.Right)
|
||||
{
|
||||
OnDragHorizontal(horizontalChange);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (e.Key == Windows.System.VirtualKey.Up)
|
||||
{
|
||||
OnDragVertical(-KeyboardIncrement);
|
||||
}
|
||||
else if (e.Key == Windows.System.VirtualKey.Down)
|
||||
{
|
||||
OnDragVertical(KeyboardIncrement);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void OnManipulationStarting(ManipulationStartingRoutedEventArgs e)
|
||||
{
|
||||
base.OnManipulationStarting(e);
|
||||
|
||||
OnDragStarting();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void OnManipulationDelta(ManipulationDeltaRoutedEventArgs e)
|
||||
{
|
||||
// We use Trancate here to provide 'snapping' points with the DragIncrement property
|
||||
// It works for both our negative and positive values, as otherwise we'd need to use
|
||||
// Ceiling when negative and Floor when positive to maintain the correct behavior.
|
||||
var horizontalChange =
|
||||
Math.Truncate(e.Cumulative.Translation.X / DragIncrement) * DragIncrement;
|
||||
var verticalChange =
|
||||
Math.Truncate(e.Cumulative.Translation.Y / DragIncrement) * DragIncrement;
|
||||
|
||||
// Important: adjust for RTL language flow settings and invert horizontal axis
|
||||
#if !HAS_UNO
|
||||
if (this.FlowDirection == FlowDirection.RightToLeft)
|
||||
{
|
||||
horizontalChange *= -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (Orientation == Orientation.Vertical)
|
||||
{
|
||||
if (!OnDragHorizontal(horizontalChange))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (Orientation == Orientation.Horizontal)
|
||||
{
|
||||
if (!OnDragVertical(verticalChange))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
base.OnManipulationDelta(e);
|
||||
}
|
||||
|
||||
// private helper bools for Visual States
|
||||
private bool _pressed = false;
|
||||
private bool _dragging = false;
|
||||
private bool _pointerEntered = false;
|
||||
|
||||
private void SizerBase_PointerReleased(object sender, PointerRoutedEventArgs e)
|
||||
{
|
||||
_pressed = false;
|
||||
|
||||
if (IsEnabled)
|
||||
{
|
||||
VisualStateManager.GoToState(this, _pointerEntered ? "PointerOver" : "Normal", true);
|
||||
}
|
||||
}
|
||||
|
||||
private void SizerBase_PointerPressed(object sender, PointerRoutedEventArgs e)
|
||||
{
|
||||
_pressed = true;
|
||||
|
||||
if (IsEnabled)
|
||||
{
|
||||
VisualStateManager.GoToState(this, "Pressed", true);
|
||||
}
|
||||
}
|
||||
|
||||
private void SizerBase_PointerExited(object sender, PointerRoutedEventArgs e)
|
||||
{
|
||||
_pointerEntered = false;
|
||||
|
||||
if (!_pressed && !_dragging && IsEnabled)
|
||||
{
|
||||
VisualStateManager.GoToState(this, "Normal", true);
|
||||
}
|
||||
}
|
||||
|
||||
private void SizerBase_PointerEntered(object sender, PointerRoutedEventArgs e)
|
||||
{
|
||||
_pointerEntered = true;
|
||||
|
||||
if (!_pressed && !_dragging && IsEnabled)
|
||||
{
|
||||
VisualStateManager.GoToState(this, "PointerOver", true);
|
||||
}
|
||||
}
|
||||
|
||||
private void SizerBase_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
|
||||
{
|
||||
_dragging = false;
|
||||
_pressed = false;
|
||||
VisualStateManager.GoToState(this, _pointerEntered ? "PointerOver" : "Normal", true);
|
||||
}
|
||||
|
||||
private void SizerBase_ManipulationStarted(object sender, ManipulationStartedRoutedEventArgs e)
|
||||
{
|
||||
_dragging = true;
|
||||
VisualStateManager.GoToState(this, "Pressed", true);
|
||||
}
|
||||
|
||||
private void SizerBase_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
if (!IsEnabled)
|
||||
{
|
||||
VisualStateManager.GoToState(this, "Disabled", true);
|
||||
}
|
||||
else
|
||||
{
|
||||
VisualStateManager.GoToState(this, _pointerEntered ? "PointerOver" : "Normal", true);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,69 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace CommunityToolkit.Labs.WinUI;
|
||||
|
||||
/// <summary>
|
||||
/// Protected helper methods for <see cref="SizerBase"/> and subclasses.
|
||||
/// </summary>
|
||||
public partial class SizerBase : Control
|
||||
{
|
||||
/// <summary>
|
||||
/// Check for new requested vertical size is valid or not
|
||||
/// </summary>
|
||||
/// <param name="target">Target control being resized</param>
|
||||
/// <param name="newHeight">The requested new height</param>
|
||||
/// <param name="parentActualHeight">The parent control's ActualHeight</param>
|
||||
/// <returns>Bool result if requested vertical change is valid or not</returns>
|
||||
protected static bool IsValidHeight(FrameworkElement target, double newHeight, double parentActualHeight)
|
||||
{
|
||||
var minHeight = target.MinHeight;
|
||||
if (newHeight < 0 || (!double.IsNaN(minHeight) && newHeight < minHeight))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var maxHeight = target.MaxHeight;
|
||||
if (!double.IsNaN(maxHeight) && newHeight > maxHeight)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (newHeight <= parentActualHeight)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check for new requested horizontal size is valid or not
|
||||
/// </summary>
|
||||
/// <param name="target">Target control being resized</param>
|
||||
/// <param name="newWidth">The requested new width</param>
|
||||
/// <param name="parentActualWidth">The parent control's ActualWidth</param>
|
||||
/// <returns>Bool result if requested horizontal change is valid or not</returns>
|
||||
protected static bool IsValidWidth(FrameworkElement target, double newWidth, double parentActualWidth)
|
||||
{
|
||||
var minWidth = target.MinWidth;
|
||||
if (newWidth < 0 || (!double.IsNaN(minWidth) && newWidth < minWidth))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var maxWidth = target.MaxWidth;
|
||||
if (!double.IsNaN(maxWidth) && newWidth > maxWidth)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (newWidth <= parentActualWidth)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -1,128 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
#if !WINAPPSDK
|
||||
using CursorEnum = Windows.UI.Core.CoreCursorType;
|
||||
#else
|
||||
using Microsoft.UI.Input;
|
||||
using CursorEnum = Microsoft.UI.Input.InputSystemCursorShape;
|
||||
#endif
|
||||
|
||||
namespace CommunityToolkit.Labs.WinUI;
|
||||
|
||||
/// <summary>
|
||||
/// Properties for <see cref="SizerBase"/>
|
||||
/// </summary>
|
||||
public partial class SizerBase : Control
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the cursor to use when hovering over the gripper bar. If left as <c>null</c>, the control will manage the cursor automatically based on the <see cref="Orientation"/> property value.
|
||||
/// </summary>
|
||||
public CursorEnum Cursor
|
||||
{
|
||||
get { return (CursorEnum)GetValue(CursorProperty); }
|
||||
set { SetValue(CursorProperty, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Identifies the <see cref="Cursor"/> dependency property.
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty CursorProperty =
|
||||
DependencyProperty.Register(nameof(Cursor), typeof(CursorEnum), typeof(SizerBase), new PropertyMetadata(null, OnOrientationPropertyChanged));
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the incremental amount of change for draging with the mouse or touch of a sizer control. Effectively a snapping increment for changes. The default is 1.
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// For instance, if the DragIncrement is set to 16. Then when a component is resized with the sizer, it will only increase or decrease in size in that increment. I.e. -16, 0, 16, 32, 48, etc...
|
||||
/// </example>
|
||||
/// <remarks>
|
||||
/// This value is indepedent of the <see cref="KeyboardIncrement"/> property. If you need to provide consistent snapping when moving regardless of input device, set these properties to the same value.
|
||||
/// </remarks>
|
||||
public double DragIncrement
|
||||
{
|
||||
get { return (double)GetValue(DragIncrementProperty); }
|
||||
set { SetValue(DragIncrementProperty, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Identifies the <see cref="DragIncrement"/> dependency property.
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty DragIncrementProperty =
|
||||
DependencyProperty.Register(nameof(DragIncrement), typeof(double), typeof(SizerBase), new PropertyMetadata(1d));
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the distance each press of an arrow key moves a sizer control. The default is 8.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This value is independent of the <see cref="DragIncrement"/> setting when using mouse/touch. If you want a consistent behavior regardless of input device, set them to the same value if snapping is required.
|
||||
/// </remarks>
|
||||
public double KeyboardIncrement
|
||||
{
|
||||
get { return (double)GetValue(KeyboardIncrementProperty); }
|
||||
set { SetValue(KeyboardIncrementProperty, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Identifies the <see cref="KeyboardIncrement"/> dependency property.
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty KeyboardIncrementProperty =
|
||||
DependencyProperty.Register(nameof(KeyboardIncrement), typeof(double), typeof(SizerBase), new PropertyMetadata(8d));
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the orientation the sizer will be and how it will interact with other elements. Defaults to <see cref="Orientation.Vertical"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Note if using <see cref="GridSplitter"/>, use the <see cref="GridSplitter.ResizeDirection"/> property instead.
|
||||
/// </remarks>
|
||||
public Orientation Orientation
|
||||
{
|
||||
get { return (Orientation)GetValue(OrientationProperty); }
|
||||
set { SetValue(OrientationProperty, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Identifies the <see cref="Orientation"/> dependency property.
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty OrientationProperty =
|
||||
DependencyProperty.Register(nameof(Orientation), typeof(Orientation), typeof(SizerBase), new PropertyMetadata(Orientation.Vertical, OnOrientationPropertyChanged));
|
||||
|
||||
private static void OnOrientationPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
if (d is SizerBase gripper)
|
||||
{
|
||||
CursorEnum cursorToUse = gripper.Orientation == Orientation.Vertical ? CursorEnum.SizeWestEast : CursorEnum.SizeNorthSouth;
|
||||
|
||||
// See if there's been a cursor override, otherwise we'll pick
|
||||
var cursor = gripper.ReadLocalValue(CursorProperty);
|
||||
if (cursor == DependencyProperty.UnsetValue || cursor == null)
|
||||
{
|
||||
cursor = cursorToUse;
|
||||
|
||||
// On UWP, we use the extension in XAML to control this behavior,
|
||||
// so we'll update it here (and maintain binding).
|
||||
// We'll keep it in-sync to maintain behavior for WinUI 3 as well.
|
||||
gripper.SetValue(CursorProperty, cursor);
|
||||
|
||||
// We return here, as the Cursor will trigger this function again anyway to set for WinUI 3
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: [UNO] Only supported on certain platforms
|
||||
// See ProtectedCursor here: https://github.com/unoplatform/uno/blob/3fe3862b270b99dbec4d830b547942af61b1a1d9/src/Uno.UI/UI/Xaml/UIElement.cs#L1015-L1023
|
||||
#if WINAPPSDK && !HAS_UNO
|
||||
// Need to wait until we're at least applying template step of loading before setting Cursor
|
||||
// See https://github.com/microsoft/microsoft-ui-xaml/issues/7062
|
||||
if (gripper._applyingTemplate &&
|
||||
cursor is CursorEnum cursorToSet &&
|
||||
(gripper.ProtectedCursor == null ||
|
||||
(gripper.ProtectedCursor is InputSystemCursor current &&
|
||||
current.CursorShape != cursorToSet)))
|
||||
{
|
||||
gripper.ProtectedCursor = InputSystemCursor.Create(cursorToSet);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,130 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using CommunityToolkit.Labs.WinUI.Automation.Peers;
|
||||
|
||||
namespace CommunityToolkit.Labs.WinUI;
|
||||
|
||||
/// <summary>
|
||||
/// Base class for splitting/resizing type controls like <see cref="GridSplitter"/> and <see cref="ContentSizer"/>. Acts similar to an enlarged <see cref="Windows.UI.Xaml.Controls.Primitives.Thumb"/> type control, but with keyboard support. Subclasses should override the various abstract methods here to implement their behavior.
|
||||
/// </summary>
|
||||
public abstract partial class SizerBase : Control
|
||||
{
|
||||
/// <summary>
|
||||
/// Called when the control has been initialized.
|
||||
/// </summary>
|
||||
/// <param name="e">Loaded event args.</param>
|
||||
protected virtual void OnLoaded(RoutedEventArgs e)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when the <see cref="SizerBase"/> control starts to be dragged by the user.
|
||||
/// Implementor should record current state of manipulated target at this point in time.
|
||||
/// They will receive the cumulative change in <see cref="OnDragHorizontal(double)"/> or
|
||||
/// <see cref="OnDragVertical(double)"/> based on the <see cref="Orientation"/> property.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method is also called at the start of a keyboard interaction. Keyboard strokes use the same pattern to emulate a mouse movement for a single change. The appropriate
|
||||
/// <see cref="OnDragHorizontal(double)"/> or <see cref="OnDragVertical(double)"/>
|
||||
/// method will also be called after when the keyboard is used.
|
||||
/// </remarks>
|
||||
protected abstract void OnDragStarting();
|
||||
|
||||
/// <summary>
|
||||
/// Method to process the requested horizontal resize.
|
||||
/// </summary>
|
||||
/// <param name="horizontalChange">The <see cref="ManipulationDeltaRoutedEventArgs.Cumulative"/> horizontal change amount from the start in device-independent pixels DIP.</param>
|
||||
/// <returns><see cref="bool"/> indicates if a change was made</returns>
|
||||
/// <remarks>
|
||||
/// The value provided here is the cumulative change from the beginning of the
|
||||
/// manipulation. This method will be used regardless of input device. It will already
|
||||
/// be adjusted for RightToLeft <see cref="FlowDirection"/> of the containing
|
||||
/// layout/settings. It will also already account for any settings such as
|
||||
/// <see cref="DragIncrement"/> or <see cref="KeyboardIncrement"/>. The implementor
|
||||
/// just needs to use the provided value to manipulate their baseline stored
|
||||
/// in <see cref="OnDragStarting"/> to provide the desired change.
|
||||
/// </remarks>
|
||||
protected abstract bool OnDragHorizontal(double horizontalChange);
|
||||
|
||||
/// <summary>
|
||||
/// Method to process the requested vertical resize.
|
||||
/// </summary>
|
||||
/// <param name="verticalChange">The <see cref="ManipulationDeltaRoutedEventArgs.Cumulative"/> vertical change amount from the start in device-independent pixels DIP.</param>
|
||||
/// <returns><see cref="bool"/> indicates if a change was made</returns>
|
||||
/// <remarks>
|
||||
/// The value provided here is the cumulative change from the beginning of the
|
||||
/// manipulation. This method will be used regardless of input device. It will also
|
||||
/// already account for any settings such as <see cref="DragIncrement"/> or
|
||||
/// <see cref="KeyboardIncrement"/>. The implementor just needs
|
||||
/// to use the provided value to manipulate their baseline stored
|
||||
/// in <see cref="OnDragStarting"/> to provide the desired change.
|
||||
/// </remarks>
|
||||
protected abstract bool OnDragVertical(double verticalChange);
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SizerBase"/> class.
|
||||
/// </summary>
|
||||
public SizerBase()
|
||||
{
|
||||
this.DefaultStyleKey = typeof(SizerBase);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates AutomationPeer (<see cref="UIElement.OnCreateAutomationPeer"/>)
|
||||
/// </summary>
|
||||
/// <returns>An automation peer for this <see cref="SizerBase"/>.</returns>
|
||||
protected override AutomationPeer OnCreateAutomationPeer()
|
||||
{
|
||||
return new SizerAutomationPeer(this);
|
||||
}
|
||||
|
||||
// On Uno the ProtectedCursor isn't supported yet, so we don't need this value.
|
||||
#if WINAPPSDK && !HAS_UNO
|
||||
// Used to track when we're in the OnApplyTemplateStep to change ProtectedCursor value.
|
||||
private bool _applyingTemplate = false;
|
||||
#endif
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void OnApplyTemplate()
|
||||
{
|
||||
base.OnApplyTemplate();
|
||||
|
||||
// Unregister Events
|
||||
Loaded -= SizerBase_Loaded;
|
||||
PointerEntered -= SizerBase_PointerEntered;
|
||||
PointerExited -= SizerBase_PointerExited;
|
||||
PointerPressed -= SizerBase_PointerPressed;
|
||||
PointerReleased -= SizerBase_PointerReleased;
|
||||
ManipulationStarted -= SizerBase_ManipulationStarted;
|
||||
ManipulationCompleted -= SizerBase_ManipulationCompleted;
|
||||
IsEnabledChanged -= SizerBase_IsEnabledChanged;
|
||||
|
||||
// Register Events
|
||||
Loaded += SizerBase_Loaded;
|
||||
PointerEntered += SizerBase_PointerEntered;
|
||||
PointerExited += SizerBase_PointerExited;
|
||||
PointerPressed += SizerBase_PointerPressed;
|
||||
PointerReleased += SizerBase_PointerReleased;
|
||||
ManipulationStarted += SizerBase_ManipulationStarted;
|
||||
ManipulationCompleted += SizerBase_ManipulationCompleted;
|
||||
IsEnabledChanged += SizerBase_IsEnabledChanged;
|
||||
|
||||
// Trigger initial state transition based on if we're Enabled or not currently.
|
||||
SizerBase_IsEnabledChanged(this, null!);
|
||||
#if WINAPPSDK && !HAS_UNO
|
||||
// On WinAppSDK, we'll trigger this to setup the initial ProtectedCursor value.
|
||||
_applyingTemplate = true;
|
||||
#endif
|
||||
// On UWP, we'll check the current Orientation and set the Cursor property to use here still.
|
||||
OnOrientationPropertyChanged(this, null!);
|
||||
}
|
||||
|
||||
private void SizerBase_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Loaded -= SizerBase_Loaded;
|
||||
|
||||
OnLoaded(e);
|
||||
}
|
||||
}
|
|
@ -1,86 +0,0 @@
|
|||
<!-- Licensed to the .NET Foundation under one or more agreements. The .NET Foundation licenses this file to you under the MIT license. See the LICENSE file in the project root for more information. -->
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="using:CommunityToolkit.Labs.WinUI"
|
||||
xmlns:local="using:CommunityToolkit.Labs.WinUI.SizerBaseLocal"
|
||||
xmlns:ui="using:Microsoft.Toolkit.Uwp.UI"
|
||||
xmlns:win="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
|
||||
<ResourceDictionary.ThemeDictionaries>
|
||||
<ResourceDictionary x:Key="Default">
|
||||
<SolidColorBrush x:Key="GripperBarBackgroundPointerOver"
|
||||
Color="{ThemeResource SystemBaseLowColor}" />
|
||||
<SolidColorBrush x:Key="GripperBarBackgroundPressedOver"
|
||||
Color="{ThemeResource SystemBaseHighColor}" />
|
||||
<SolidColorBrush x:Key="GripperBarForeground"
|
||||
Color="{ThemeResource SystemAltHighColor}" />
|
||||
</ResourceDictionary>
|
||||
<ResourceDictionary x:Key="HighContrast">
|
||||
<SolidColorBrush x:Key="GripperBarBackgroundPointerOver"
|
||||
Color="{ThemeResource SystemColorHighlightColor}" />
|
||||
<SolidColorBrush x:Key="GripperBarBackgroundPressedOver"
|
||||
Color="{ThemeResource SystemColorHighlightColor}" />
|
||||
<SolidColorBrush x:Key="GripperBarForeground"
|
||||
Color="{ThemeResource SystemAltHighColor}" />
|
||||
</ResourceDictionary>
|
||||
</ResourceDictionary.ThemeDictionaries>
|
||||
|
||||
<local:OrientationToObjectConverter x:Key="OrientationToGlyphConverter"
|
||||
HorizontalValue=""
|
||||
VerticalValue="" />
|
||||
|
||||
<StaticResource x:Key="GripperBarFontFamily"
|
||||
ResourceKey="SymbolThemeFontFamily" />
|
||||
|
||||
<Style TargetType="controls:SizerBase">
|
||||
<Setter Property="IsTabStop" Value="True" />
|
||||
<Setter Property="UseSystemFocusVisuals" Value="True" />
|
||||
<Setter Property="HorizontalAlignment" Value="Stretch" />
|
||||
<Setter Property="VerticalAlignment" Value="Stretch" />
|
||||
<Setter Property="IsFocusEngagementEnabled" Value="True" />
|
||||
<Setter Property="MinWidth" Value="16" />
|
||||
<Setter Property="MinHeight" Value="16" />
|
||||
<Setter Property="Background" Value="{ThemeResource SystemControlHighlightChromeHighBrush}" />
|
||||
<Setter Property="HorizontalContentAlignment" Value="Center" />
|
||||
<Setter Property="VerticalContentAlignment" Value="Center" />
|
||||
<Setter Property="AutomationProperties.Name" Value="ms-resource://CommunityToolkit.Labs.WinUI.SizerBase/CommunityToolkit.Labs.WinUI.SizerBase/Resources/WCT_SizerBase_AutomationName" />
|
||||
<Setter Property="ManipulationMode" Value="TranslateX,TranslateY" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="controls:SizerBase">
|
||||
<Grid x:Name="RootGrid"
|
||||
local:FrameworkElementExtensions.Cursor="{TemplateBinding Cursor}"
|
||||
Background="{TemplateBinding Background}">
|
||||
|
||||
<!-- Note: These align with Thumb -->
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="PointerOver">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="RootGrid.Background" Value="{ThemeResource GripperBarBackgroundPointerOver}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="Pressed">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="RootGrid.Background" Value="{ThemeResource GripperBarBackgroundPressedOver}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<!-- TODO -->
|
||||
<VisualState x:Name="Disabled" />
|
||||
</VisualStateGroup>
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
|
||||
<TextBlock HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
win:AutomationProperties.AccessibilityView="Raw"
|
||||
FontFamily="{ThemeResource GripperBarFontFamily}"
|
||||
Foreground="{ThemeResource GripperBarForeground}"
|
||||
Text="{Binding Orientation, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource OrientationToGlyphConverter}}" />
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
</ResourceDictionary>
|
|
@ -1,124 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="WCT_SizerBase_AutomationName" xml:space="preserve">
|
||||
<value>Sizer</value>
|
||||
<comment>Narrator Resource for SizerBase controls and similar</comment>
|
||||
</data>
|
||||
</root>
|
|
@ -1,7 +0,0 @@
|
|||
<!-- Licensed to the .NET Foundation under one or more agreements. The .NET Foundation licenses this file to you under the MIT license. See the LICENSE file in the project root for more information. -->
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="ms-appx:///CommunityToolkit.Labs.WinUI.SizerBase/SizerBase.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
|
@ -1,45 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace CommunityToolkit.Labs.WinUI.SizerBaseLocal;
|
||||
|
||||
/// <summary>
|
||||
/// Static class used to provide internal tools
|
||||
/// </summary>
|
||||
internal static class ConverterTools
|
||||
{
|
||||
/// <summary>
|
||||
/// Helper method to safely cast an object to a boolean
|
||||
/// </summary>
|
||||
/// <param name="parameter">Parameter to cast to a boolean</param>
|
||||
/// <returns>Bool value or false if cast failed</returns>
|
||||
internal static bool TryParseBool(object parameter)
|
||||
{
|
||||
var parsed = false;
|
||||
if (parameter != null)
|
||||
{
|
||||
bool.TryParse(parameter.ToString(), out parsed);
|
||||
}
|
||||
|
||||
return parsed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to convert a value from a source type to a target type.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to convert</param>
|
||||
/// <param name="targetType">The target type</param>
|
||||
/// <returns>The converted value</returns>
|
||||
internal static object Convert(object value, Type targetType)
|
||||
{
|
||||
if (targetType.IsInstanceOfType(value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
else
|
||||
{
|
||||
return XamlBindingHelper.ConvertValue(targetType, value);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,225 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
// We want this to be private/local to our component.
|
||||
namespace CommunityToolkit.Labs.WinUI.SizerBaseLocal;
|
||||
|
||||
//// IMPORTANT NOTE: This is the old 6.1.1 version of the extensions as I had issues with TPredicate with the new ones here for some reason and just wanted to get this working for now.
|
||||
|
||||
/// <summary>
|
||||
/// Defines a collection of extensions methods for UI.
|
||||
/// </summary>
|
||||
public static class VisualTree
|
||||
{
|
||||
/// <summary>
|
||||
/// Find descendant <see cref="FrameworkElement"/> control using its name.
|
||||
/// </summary>
|
||||
/// <param name="element">Parent element.</param>
|
||||
/// <param name="name">Name of the control to find</param>
|
||||
/// <returns>Descendant control or null if not found.</returns>
|
||||
public static FrameworkElement? FindDescendantByName(this DependencyObject element, string name)
|
||||
{
|
||||
if (element == null || string.IsNullOrWhiteSpace(name))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (name.Equals((element as FrameworkElement)?.Name, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return element as FrameworkElement;
|
||||
}
|
||||
|
||||
var childCount = VisualTreeHelper.GetChildrenCount(element);
|
||||
for (int i = 0; i < childCount; i++)
|
||||
{
|
||||
var result = VisualTreeHelper.GetChild(element, i).FindDescendantByName(name);
|
||||
if (result != null)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Find first descendant control of a specified type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type to search for.</typeparam>
|
||||
/// <param name="element">Parent element.</param>
|
||||
/// <returns>Descendant control or null if not found.</returns>
|
||||
public static T? FindDescendant<T>(this DependencyObject element)
|
||||
where T : DependencyObject
|
||||
{
|
||||
T? retValue = default(T);
|
||||
var childrenCount = VisualTreeHelper.GetChildrenCount(element);
|
||||
|
||||
for (var i = 0; i < childrenCount; i++)
|
||||
{
|
||||
var child = VisualTreeHelper.GetChild(element, i);
|
||||
if (child is T type)
|
||||
{
|
||||
retValue = type;
|
||||
break;
|
||||
}
|
||||
|
||||
retValue = FindDescendant<T>(child);
|
||||
|
||||
if (retValue != null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return retValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Find first descendant control of a specified type.
|
||||
/// </summary>
|
||||
/// <param name="element">Parent element.</param>
|
||||
/// <param name="type">Type of descendant.</param>
|
||||
/// <returns>Descendant control or null if not found.</returns>
|
||||
public static object? FindDescendant(this DependencyObject element, Type type)
|
||||
{
|
||||
object? retValue = null;
|
||||
var childrenCount = VisualTreeHelper.GetChildrenCount(element);
|
||||
|
||||
for (var i = 0; i < childrenCount; i++)
|
||||
{
|
||||
var child = VisualTreeHelper.GetChild(element, i);
|
||||
if (child.GetType() == type)
|
||||
{
|
||||
retValue = child;
|
||||
break;
|
||||
}
|
||||
|
||||
retValue = FindDescendant(child, type);
|
||||
|
||||
if (retValue != null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return retValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Find all descendant controls of the specified type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type to search for.</typeparam>
|
||||
/// <param name="element">Parent element.</param>
|
||||
/// <returns>Descendant controls or empty if not found.</returns>
|
||||
public static IEnumerable<T> FindDescendants<T>(this DependencyObject element)
|
||||
where T : DependencyObject
|
||||
{
|
||||
var childrenCount = VisualTreeHelper.GetChildrenCount(element);
|
||||
|
||||
for (var i = 0; i < childrenCount; i++)
|
||||
{
|
||||
var child = VisualTreeHelper.GetChild(element, i);
|
||||
if (child is T type)
|
||||
{
|
||||
yield return type;
|
||||
}
|
||||
|
||||
foreach (T childofChild in child.FindDescendants<T>())
|
||||
{
|
||||
yield return childofChild;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Find visual ascendant <see cref="FrameworkElement"/> control using its name.
|
||||
/// </summary>
|
||||
/// <param name="element">Parent element.</param>
|
||||
/// <param name="name">Name of the control to find</param>
|
||||
/// <returns>Descendant control or null if not found.</returns>
|
||||
public static FrameworkElement? FindAscendantByName(this DependencyObject element, string name)
|
||||
{
|
||||
if (element == null || string.IsNullOrWhiteSpace(name))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var parent = VisualTreeHelper.GetParent(element);
|
||||
|
||||
if (parent == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (name.Equals((parent as FrameworkElement)?.Name, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return parent as FrameworkElement;
|
||||
}
|
||||
|
||||
return parent.FindAscendantByName(name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Find first visual ascendant control of a specified type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type to search for.</typeparam>
|
||||
/// <param name="element">Child element.</param>
|
||||
/// <returns>Ascendant control or null if not found.</returns>
|
||||
public static T? FindAscendant<T>(this DependencyObject element)
|
||||
where T : DependencyObject
|
||||
{
|
||||
var parent = VisualTreeHelper.GetParent(element);
|
||||
|
||||
if (parent == null)
|
||||
{
|
||||
return default(T);
|
||||
}
|
||||
|
||||
if (parent is T rtn)
|
||||
{
|
||||
return rtn;
|
||||
}
|
||||
|
||||
return parent.FindAscendant<T>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Find first visual ascendant control of a specified type.
|
||||
/// </summary>
|
||||
/// <param name="element">Child element.</param>
|
||||
/// <param name="type">Type of ascendant to look for.</param>
|
||||
/// <returns>Ascendant control or null if not found.</returns>
|
||||
public static object? FindAscendant(this DependencyObject element, Type type)
|
||||
{
|
||||
var parent = VisualTreeHelper.GetParent(element);
|
||||
|
||||
if (parent == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (parent.GetType() == type)
|
||||
{
|
||||
return parent;
|
||||
}
|
||||
|
||||
return parent.FindAscendant(type);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Find all visual ascendants for the element.
|
||||
/// </summary>
|
||||
/// <param name="element">Child element.</param>
|
||||
/// <returns>A collection of parent elements or null if none found.</returns>
|
||||
public static IEnumerable<DependencyObject> FindAscendants(this DependencyObject element)
|
||||
{
|
||||
var parent = VisualTreeHelper.GetParent(element);
|
||||
|
||||
while (parent != null)
|
||||
{
|
||||
yield return parent;
|
||||
parent = VisualTreeHelper.GetParent(parent);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,113 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Windows.UI.Core;
|
||||
|
||||
namespace CommunityToolkit.Labs.WinUI.SizerBaseLocal;
|
||||
|
||||
/// <inheritdoc cref="FrameworkElementExtensions"/>
|
||||
public static partial class FrameworkElementExtensions
|
||||
{
|
||||
private static readonly object _cursorLock = new object();
|
||||
private static readonly CoreCursor _defaultCursor = new CoreCursor(CoreCursorType.Arrow, 1);
|
||||
private static readonly Dictionary<CoreCursorType, CoreCursor> _cursors =
|
||||
new Dictionary<CoreCursorType, CoreCursor> { { CoreCursorType.Arrow, _defaultCursor } };
|
||||
|
||||
/// <summary>
|
||||
/// Dependency property for specifying the target <see cref="CoreCursorType"/> to be shown
|
||||
/// over the target <see cref="FrameworkElement"/>.
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty CursorProperty =
|
||||
DependencyProperty.RegisterAttached("Cursor", typeof(CoreCursorType), typeof(FrameworkElementExtensions), new PropertyMetadata(CoreCursorType.Arrow, CursorChanged));
|
||||
|
||||
/// <summary>
|
||||
/// Set the target <see cref="CoreCursorType"/>.
|
||||
/// </summary>
|
||||
/// <param name="element">Object where the selector cursor type should be shown.</param>
|
||||
/// <param name="value">Target cursor type value.</param>
|
||||
public static void SetCursor(FrameworkElement element, CoreCursorType value)
|
||||
{
|
||||
element.SetValue(CursorProperty, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the current <see cref="CoreCursorType"/>.
|
||||
/// </summary>
|
||||
/// <param name="element">Object where the selector cursor type should be shown.</param>
|
||||
/// <returns>Cursor type set on target element.</returns>
|
||||
public static CoreCursorType GetCursor(FrameworkElement element)
|
||||
{
|
||||
return (CoreCursorType)element.GetValue(CursorProperty);
|
||||
}
|
||||
|
||||
private static void CursorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
// TODO: How do we want to indicate this isn't supported on the WinAppSDK?
|
||||
#if !WINAPPSDK
|
||||
var element = d as FrameworkElement;
|
||||
if (element == null)
|
||||
{
|
||||
throw new NullReferenceException(nameof(element));
|
||||
}
|
||||
|
||||
var value = (CoreCursorType)e.NewValue;
|
||||
|
||||
// lock ensures CoreCursor creation and event handlers attachment/detachment is atomic
|
||||
lock (_cursorLock)
|
||||
{
|
||||
if (!_cursors.ContainsKey(value))
|
||||
{
|
||||
_cursors[value] = new CoreCursor(value, 1);
|
||||
}
|
||||
|
||||
// make sure event handlers are not attached twice to element
|
||||
element.PointerEntered -= Element_PointerEntered;
|
||||
element.PointerEntered += Element_PointerEntered;
|
||||
element.PointerExited -= Element_PointerExited;
|
||||
element.PointerExited += Element_PointerExited;
|
||||
element.Unloaded -= ElementOnUnloaded;
|
||||
element.Unloaded += ElementOnUnloaded;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !WINAPPSDK
|
||||
private static void Element_PointerEntered(object sender, PointerRoutedEventArgs e)
|
||||
{
|
||||
// TODO: [UNO] Only supported on certain platforms
|
||||
// See PointerCursor here: https://github.com/unoplatform/uno/blob/3fe3862b270b99dbec4d830b547942af61b1a1d9/src/Uno.UWP/UI/Core/CoreWindow.cs#L71-L77
|
||||
#if NETFX_CORE || WASM || __MACOS__ || __SKIA__
|
||||
CoreCursorType cursor = GetCursor((FrameworkElement)sender);
|
||||
Window.Current.CoreWindow.PointerCursor = _cursors[cursor];
|
||||
#endif
|
||||
}
|
||||
|
||||
private static void Element_PointerExited(object sender, PointerRoutedEventArgs e)
|
||||
{
|
||||
#if NETFX_CORE || WASM || __MACOS__ || __SKIA__
|
||||
// when exiting change the cursor to the target Mouse.Cursor value of the new element
|
||||
CoreCursor cursor;
|
||||
if (sender != e.OriginalSource && e.OriginalSource is FrameworkElement newElement)
|
||||
{
|
||||
cursor = _cursors[GetCursor(newElement)];
|
||||
}
|
||||
else
|
||||
{
|
||||
cursor = _defaultCursor;
|
||||
}
|
||||
|
||||
Window.Current.CoreWindow.PointerCursor = cursor;
|
||||
#endif
|
||||
}
|
||||
|
||||
private static void ElementOnUnloaded(object sender, RoutedEventArgs routedEventArgs)
|
||||
{
|
||||
#if NETFX_CORE || __WASM__ || __MACOS__ || __SKIA__
|
||||
// when the element is programatically unloaded, reset the cursor back to default
|
||||
// this is necessary when click triggers immediate change in layout and PointerExited is not called
|
||||
Window.Current.CoreWindow.PointerCursor = _defaultCursor;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
|
@ -1,76 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace CommunityToolkit.Labs.WinUI.SizerBaseLocal;
|
||||
|
||||
/// <summary>
|
||||
/// This class returns a value depending on the <see cref="Orientation"/> of the value provided to the converter. In case of default will return the <see cref="VerticalValue"/>.
|
||||
/// </summary>
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1001:Types that own disposable fields should be disposable", Justification = "Internal Uno Generator Issue: https://github.com/unoplatform/uno/pull/8743")]
|
||||
public partial class OrientationToObjectConverter : DependencyObject, IValueConverter
|
||||
{
|
||||
/// <summary>
|
||||
/// Identifies the <see cref="HorizontalValue"/> property.
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty HorizontalValueProperty =
|
||||
DependencyProperty.Register(nameof(HorizontalValue), typeof(object), typeof(OrientationToObjectConverter), new PropertyMetadata(null));
|
||||
|
||||
/// <summary>
|
||||
/// Identifies the <see cref="VerticalValue"/> property.
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty VerticalValueProperty =
|
||||
DependencyProperty.Register(nameof(VerticalValue), typeof(object), typeof(OrientationToObjectConverter), new PropertyMetadata(null));
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the value to be returned when the <see cref="Orientation"/> of the provided value is <see cref="Orientation.Horizontal"/>.
|
||||
/// </summary>
|
||||
public object HorizontalValue
|
||||
{
|
||||
get { return GetValue(HorizontalValueProperty); }
|
||||
set { SetValue(HorizontalValueProperty, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the value to be returned when the <see cref="Orientation"/> of the provided value is <see cref="Orientation.Vertical"/>.
|
||||
/// </summary>
|
||||
public object VerticalValue
|
||||
{
|
||||
get { return GetValue(VerticalValueProperty); }
|
||||
set { SetValue(VerticalValueProperty, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert the <paramref name="value"/>'s Orientation to an other object.
|
||||
/// </summary>
|
||||
/// <param name="value">The source data being passed to the target.</param>
|
||||
/// <param name="targetType">The type of the target property, as a type reference.</param>
|
||||
/// <param name="parameter">An optional parameter to be used to invert the converter logic.</param>
|
||||
/// <param name="language">The language of the conversion.</param>
|
||||
/// <returns>The value to be passed to the target dependency property.</returns>
|
||||
public object Convert(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
var isHorizontal = value != null && value is Orientation orientation && orientation == Orientation.Horizontal;
|
||||
|
||||
// Negate if needed
|
||||
if (ConverterTools.TryParseBool(parameter))
|
||||
{
|
||||
isHorizontal = !isHorizontal;
|
||||
}
|
||||
|
||||
return ConverterTools.Convert(isHorizontal ? HorizontalValue : VerticalValue, targetType);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Not implemented.
|
||||
/// </summary>
|
||||
/// <param name="value">The source data being passed to the target.</param>
|
||||
/// <param name="targetType">The type of the target property, as a type reference.</param>
|
||||
/// <param name="parameter">Optional parameter. Not used.</param>
|
||||
/// <param name="language">The language of the conversion. Not used.</param>
|
||||
/// <returns>The value to be passed to the target dependency property.</returns>
|
||||
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
|
@ -1,91 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace CommunityToolkit.Labs.WinUI.SizerBaseLocal;
|
||||
|
||||
/// <summary>
|
||||
/// This class returns an object or another, depending on whether the type of the provided value matches another provided Type.
|
||||
/// </summary>
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1001:Types that own disposable fields should be disposable", Justification = "Internal Uno Generator Issue: https://github.com/unoplatform/uno/pull/8743")]
|
||||
public partial class TypeToObjectConverter : DependencyObject, IValueConverter
|
||||
{
|
||||
/// <summary>
|
||||
/// Identifies the <see cref="TrueValue"/> property.
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty TrueValueProperty =
|
||||
DependencyProperty.Register(nameof(TrueValue), typeof(object), typeof(TypeToObjectConverter), new PropertyMetadata(null));
|
||||
|
||||
/// <summary>
|
||||
/// Identifies the <see cref="FalseValue"/> property.
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty FalseValueProperty =
|
||||
DependencyProperty.Register(nameof(FalseValue), typeof(object), typeof(TypeToObjectConverter), new PropertyMetadata(null));
|
||||
|
||||
/// <summary>
|
||||
/// Identifies the <see cref="Type"/> property.
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty TypeProperty =
|
||||
DependencyProperty.Register(nameof(Type), typeof(Type), typeof(TypeToObjectConverter), new PropertyMetadata(typeof(object)));
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the value to be returned when the type of the provided value matches <see cref="Type"/>.
|
||||
/// </summary>
|
||||
public object TrueValue
|
||||
{
|
||||
get { return GetValue(TrueValueProperty); }
|
||||
set { SetValue(TrueValueProperty, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the value to be returned when the type of the provided value does not match <see cref="Type"/>.
|
||||
/// </summary>
|
||||
public object FalseValue
|
||||
{
|
||||
get { return GetValue(FalseValueProperty); }
|
||||
set { SetValue(FalseValueProperty, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Type used to compare the type of the provided value.
|
||||
/// </summary>
|
||||
public Type Type
|
||||
{
|
||||
get { return (Type)GetValue(TypeProperty); }
|
||||
set { SetValue(TypeProperty, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert the <paramref name="value"/>'s Type to an other object.
|
||||
/// </summary>
|
||||
/// <param name="value">The source data being passed to the target.</param>
|
||||
/// <param name="targetType">The type of the target property, as a type reference.</param>
|
||||
/// <param name="parameter">An optional parameter to be used to invert the converter logic.</param>
|
||||
/// <param name="language">The language of the conversion.</param>
|
||||
/// <returns>The value to be passed to the target dependency property.</returns>
|
||||
public object Convert(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
var typeMatches = value != null && Type.Equals(value.GetType());
|
||||
|
||||
// Negate if needed
|
||||
if (ConverterTools.TryParseBool(parameter))
|
||||
{
|
||||
typeMatches = !typeMatches;
|
||||
}
|
||||
|
||||
return ConverterTools.Convert(typeMatches ? TrueValue : FalseValue, targetType);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Not implemented.
|
||||
/// </summary>
|
||||
/// <param name="value">The source data being passed to the target.</param>
|
||||
/// <param name="targetType">The type of the target property, as a type reference.</param>
|
||||
/// <param name="parameter">Optional parameter. Not used.</param>
|
||||
/// <param name="language">The language of the conversion. Not used.</param>
|
||||
/// <returns>The value to be passed to the target dependency property.</returns>
|
||||
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
|
@ -1,61 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using CommunityToolkit.Labs.WinUI;
|
||||
using CommunityToolkit.Tooling.TestGen;
|
||||
using CommunityToolkit.Tests;
|
||||
using CommunityToolkit.Labs.WinUI.Automation.Peers;
|
||||
|
||||
namespace SizerBaseExperiment.Tests;
|
||||
|
||||
[TestClass]
|
||||
public partial class ExampleSizerBaseTestClass : VisualUITestBase
|
||||
{
|
||||
[TestMethod]
|
||||
public async Task ShouldConfigureGridSplitterAutomationPeer()
|
||||
{
|
||||
await EnqueueAsync(() =>
|
||||
{
|
||||
const string automationName = "MyCustomAutomationName";
|
||||
const string name = "Sizer";
|
||||
|
||||
var gridSplitter = new GridSplitter();
|
||||
var gridSplitterAutomationPeer = FrameworkElementAutomationPeer.CreatePeerForElement(gridSplitter) as SizerAutomationPeer;
|
||||
|
||||
Assert.IsNotNull(gridSplitterAutomationPeer, "Verify that the AutomationPeer is SizerAutomationPeer.");
|
||||
|
||||
gridSplitter.Name = name;
|
||||
Assert.IsTrue(gridSplitterAutomationPeer.GetName().Contains(name), "Verify that the UIA name contains the given Name of the GridSplitter (Sizer).");
|
||||
|
||||
gridSplitter.SetValue(AutomationProperties.NameProperty, automationName);
|
||||
Assert.IsTrue(gridSplitterAutomationPeer.GetName().Contains(automationName), "Verify that the UIA name contains the customized AutomationProperties.Name of the GridSplitter.");
|
||||
});
|
||||
}
|
||||
|
||||
[UIThreadTestMethod]
|
||||
public void PropertySizer_TestInitialBinding(PropertySizerTestInitialBinding testControl)
|
||||
{
|
||||
var propertySizer = testControl.FindDescendant<PropertySizer>();
|
||||
|
||||
Assert.IsNotNull(propertySizer, "Could not find PropertySizer control.");
|
||||
|
||||
// Set in XAML Page LINK: PropertySizerTestInitialBinding.xaml#L14
|
||||
Assert.AreEqual(300, propertySizer.Binding, "Property Sizer not at expected initial value.");
|
||||
}
|
||||
|
||||
[UIThreadTestMethod]
|
||||
public void PropertySizer_TestChangeBinding(PropertySizerTestInitialBinding testControl)
|
||||
{
|
||||
var propertySizer = testControl.FindDescendant<PropertySizer>();
|
||||
var navigationView = testControl.FindDescendant<MUXC.NavigationView>();
|
||||
|
||||
Assert.IsNotNull(propertySizer, "Could not find PropertySizer control.");
|
||||
Assert.IsNotNull(navigationView, "Could not find NavigationView control.");
|
||||
|
||||
navigationView.OpenPaneLength = 200;
|
||||
|
||||
// Set in XAML Page LINK: PropertySizerTestInitialBinding.xaml#L14
|
||||
Assert.AreEqual(200, propertySizer.Binding, "Property Sizer not at expected changed value.");
|
||||
}
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
<!-- Licensed to the .NET Foundation under one or more agreements. The .NET Foundation licenses this file to you under the MIT license. See the LICENSE file in the project root for more information. -->
|
||||
<Page x:Class="SizerBaseExperiment.Tests.PropertySizerTestInitialBinding"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="using:CommunityToolkit.Labs.WinUI"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<muxc:NavigationView x:Name="ViewPanel"
|
||||
MinHeight="300"
|
||||
IsPaneOpen="True"
|
||||
OpenPaneLength="300"
|
||||
PaneDisplayMode="Left">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<!-- Note the use of a TwoWay binding here, this is required for this control to work. -->
|
||||
<controls:PropertySizer HorizontalAlignment="Left"
|
||||
Binding="{x:Bind ViewPanel.OpenPaneLength, Mode=TwoWay}"
|
||||
Maximum="440"
|
||||
Minimum="52" />
|
||||
</Grid>
|
||||
</muxc:NavigationView>
|
||||
</Page>
|
|
@ -1,16 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace SizerBaseExperiment.Tests;
|
||||
|
||||
/// <summary>
|
||||
/// An empty page that can be used on its own or navigated to within a Frame.
|
||||
/// </summary>
|
||||
public sealed partial class PropertySizerTestInitialBinding : Page
|
||||
{
|
||||
public PropertySizerTestInitialBinding()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<MSBuildAllProjects Condition="'$(MSBuildVersion)' == '' Or '$(MSBuildVersion)' < '16.0'">$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
|
||||
<HasSharedItems>true</HasSharedItems>
|
||||
<SharedGUID>55883B50-C4F3-419E-B235-C51279EB4055</SharedGUID>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Configuration">
|
||||
<Import_RootNamespace>SizerBaseExperiment.Tests</Import_RootNamespace>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="$(MSBuildThisFileDirectory)ExampleSizerBaseTestClass.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)PropertySizerTestInitialBinding.xaml.cs">
|
||||
<DependentUpon>PropertySizerTestInitialBinding.xaml</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Include="$(MSBuildThisFileDirectory)PropertySizerTestInitialBinding.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -1,13 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>55883B50-C4F3-419E-B235-C51279EB4055</ProjectGuid>
|
||||
<MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.Default.props" />
|
||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.props" />
|
||||
<PropertyGroup />
|
||||
<Import Project="SizerBase.Tests.projitems" Label="Shared" />
|
||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.CSharp.targets" />
|
||||
</Project>
|
Загрузка…
Ссылка в новой задаче