Merge pull request #479 from CommunityToolkit/niels9001/remove
Removing SettingsControls and Sizers
This commit is contained in:
Коммит
a5771031e6
|
@ -1,3 +0,0 @@
|
|||
@ECHO OFF
|
||||
|
||||
powershell ..\..\tooling\ProjectHeads\GenerateSingleSampleHeads.ps1 -componentPath %CD% %*
|
Двоичные данные
components/SettingsControls/samples/Assets/SettingsCard.png
Двоичные данные
components/SettingsControls/samples/Assets/SettingsCard.png
Двоичный файл не отображается.
До Ширина: | Высота: | Размер: 3.8 KiB |
Двоичные данные
components/SettingsControls/samples/Assets/SettingsExpander.png
Двоичные данные
components/SettingsControls/samples/Assets/SettingsExpander.png
Двоичный файл не отображается.
До Ширина: | Высота: | Размер: 3.8 KiB |
|
@ -1,42 +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="SettingsControlsExperiment.Samples.ClickableSettingsCardSample"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:labs="using:CommunityToolkit.Labs.WinUI"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d">
|
||||
<StackPanel Spacing="3">
|
||||
|
||||
<labs:SettingsCard x:Name="settingsCard"
|
||||
Description="A SettingsCard can be made clickable and you can leverage the Command property or Click event."
|
||||
Header="A clickable SettingsCard"
|
||||
IsClickEnabled="True"
|
||||
IsEnabled="{x:Bind IsCardEnabled, Mode=OneWay}">
|
||||
<labs:SettingsCard.HeaderIcon>
|
||||
<FontIcon Glyph="" />
|
||||
</labs:SettingsCard.HeaderIcon>
|
||||
</labs:SettingsCard>
|
||||
|
||||
<labs:SettingsCard ActionIconToolTip="Open in new window"
|
||||
Description="You can customize the ActionIcon and ActionIconToolTip."
|
||||
Header="Customizing the ActionIcon"
|
||||
IsClickEnabled="True"
|
||||
IsEnabled="{x:Bind IsCardEnabled, Mode=OneWay}">
|
||||
<labs:SettingsCard.HeaderIcon>
|
||||
<FontIcon Glyph="" />
|
||||
</labs:SettingsCard.HeaderIcon>
|
||||
<labs:SettingsCard.ActionIcon>
|
||||
<FontIcon Glyph="" />
|
||||
</labs:SettingsCard.ActionIcon>
|
||||
</labs:SettingsCard>
|
||||
<labs:SettingsCard Header="Hiding the ActionIcon"
|
||||
IsActionIconVisible="False"
|
||||
IsClickEnabled="True"
|
||||
IsEnabled="{x:Bind IsCardEnabled, Mode=OneWay}">
|
||||
<labs:SettingsCard.HeaderIcon>
|
||||
<FontIcon Glyph="" />
|
||||
</labs:SettingsCard.HeaderIcon>
|
||||
</labs:SettingsCard>
|
||||
</StackPanel>
|
||||
</Page>
|
|
@ -1,23 +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.ComponentModel;
|
||||
|
||||
namespace SettingsControlsExperiment.Samples;
|
||||
|
||||
[ToolkitSampleBoolOption("IsCardEnabled", true, Title = "Is Enabled")]
|
||||
|
||||
[ToolkitSample(id: nameof(ClickableSettingsCardSample), "ClickableSettingsCardSample", description: "A sample for showing how SettingsCard can be static or clickable.")]
|
||||
public sealed partial class ClickableSettingsCardSample : Page
|
||||
{
|
||||
public ClickableSettingsCardSample()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
|
||||
private async void OnCardClicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
await Windows.System.Launcher.LaunchUriAsync(new Uri("https://www.microsoft.com"));
|
||||
}
|
||||
}
|
|
@ -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,22 +0,0 @@
|
|||
---
|
||||
title: SettingsCard
|
||||
author: niels9001
|
||||
description: A card control that can be used to create Windows 11 style settings experiences.
|
||||
keywords: SettingsCard, Control, Layout, Settings
|
||||
dev_langs:
|
||||
- csharp
|
||||
category: Controls
|
||||
subcategory: Layout
|
||||
discussion-id: 129
|
||||
issue-id: 216
|
||||
icon: Assets/SettingsCard.png
|
||||
---
|
||||
|
||||
SettingsCard is a control that can be used to display settings in your experience. It uses the default styling found in Windows 11 and is easy to use, meets all accesibility standards and will make your settings page look great!
|
||||
You can set the `Header`, `Description`, `HeaderIcon` and `Content` properties to create an easy to use experience, like so:
|
||||
|
||||
> [!SAMPLE SettingsCardSample]
|
||||
|
||||
SettingsCard can also be turned into a button, by setting the `IsClickEnabled` property. This can be useful whenever you want your settings component to navigate to a detail page or open an external link. You can set a custom icon by setting the `ActionIcon`, or hiding it completely by setting the `IsActionIconVisible` to `false`.
|
||||
|
||||
> [!SAMPLE ClickableSettingsCardSample]
|
|
@ -1,57 +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="SettingsControlsExperiment.Samples.SettingsCardSample"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:labs="using:CommunityToolkit.Labs.WinUI"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d">
|
||||
<StackPanel Spacing="3">
|
||||
<labs:SettingsCard x:Name="settingsCard"
|
||||
Description="This is a default card, with the Header, HeaderIcon, Description and Content set."
|
||||
Header="This is the Header"
|
||||
IsEnabled="{x:Bind IsCardEnabled, Mode=OneWay}">
|
||||
<labs:SettingsCard.HeaderIcon>
|
||||
<FontIcon Glyph="" />
|
||||
</labs:SettingsCard.HeaderIcon>
|
||||
<ComboBox SelectedIndex="0">
|
||||
<ComboBoxItem>Option 1</ComboBoxItem>
|
||||
<ComboBoxItem>Option 2</ComboBoxItem>
|
||||
<ComboBoxItem>Option 3</ComboBoxItem>
|
||||
</ComboBox>
|
||||
</labs:SettingsCard>
|
||||
|
||||
<labs:SettingsCard Description="You can use a FontIcon, SymbolIcon or BitmapIcon to set the cards HeaderIcon."
|
||||
Header="Icon options"
|
||||
IsEnabled="{x:Bind IsCardEnabled, Mode=OneWay}">
|
||||
<labs:SettingsCard.HeaderIcon>
|
||||
<BitmapIcon ShowAsMonochrome="False"
|
||||
UriSource="ms-appx:///Assets/AppTitleBar.scale-200.png" />
|
||||
</labs:SettingsCard.HeaderIcon>
|
||||
<ToggleSwitch />
|
||||
</labs:SettingsCard>
|
||||
|
||||
<labs:SettingsCard Header="A card with custom objects as its Description"
|
||||
IsEnabled="{x:Bind IsCardEnabled, Mode=OneWay}">
|
||||
<labs:SettingsCard.Description>
|
||||
<HyperlinkButton Content="Learn more about Phone Link" />
|
||||
</labs:SettingsCard.Description>
|
||||
<Button Content="Open Phone Link"
|
||||
Style="{StaticResource AccentButtonStyle}" />
|
||||
</labs:SettingsCard>
|
||||
|
||||
<labs:SettingsCard Description="When resizing a SettingsCard, the Content will wrap vertically. You can override this breakpoint by setting the SettingsCardWrapThreshold resource. For edge cases, you can also hide the icon by setting SettingsCardWrapNoIconThreshold."
|
||||
Header="Adaptive layouts"
|
||||
IsEnabled="{x:Bind IsCardEnabled, Mode=OneWay}">
|
||||
<labs:SettingsCard.HeaderIcon>
|
||||
<FontIcon Glyph="" />
|
||||
</labs:SettingsCard.HeaderIcon>
|
||||
<labs:SettingsCard.Resources>
|
||||
<x:Double x:Key="SettingsCardWrapThreshold">800</x:Double>
|
||||
<x:Double x:Key="SettingsCardWrapNoIconThreshold">600</x:Double>
|
||||
</labs:SettingsCard.Resources>
|
||||
<Button Content="This control will wrap vertically!"
|
||||
Style="{StaticResource AccentButtonStyle}" />
|
||||
</labs:SettingsCard>
|
||||
</StackPanel>
|
||||
</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 SettingsControlsExperiment.Samples;
|
||||
|
||||
[ToolkitSampleBoolOption("IsCardEnabled", true, Title = "Is Enabled")]
|
||||
|
||||
[ToolkitSample(id: nameof(SettingsCardSample), "SettingsCard", description: "A sample for showing how SettingsCard can be static or clickable.")]
|
||||
public sealed partial class SettingsCardSample : Page
|
||||
{
|
||||
public SettingsCardSample()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
<Project Sdk="MSBuild.Sdk.Extras/3.0.23">
|
||||
<PropertyGroup>
|
||||
<ToolkitComponentName>SettingsControls</ToolkitComponentName>
|
||||
<LangVersion>10.0</LangVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Sets this up as a toolkit component's sample project -->
|
||||
<Import Project="$(ToolingDirectory)\ToolkitComponent.SampleProject.props" />
|
||||
</Project>
|
|
@ -1,27 +0,0 @@
|
|||
---
|
||||
title: SettingsExpander
|
||||
author: niels9001
|
||||
description: An expander control that can be used to create Windows 11 style settings experiences.
|
||||
keywords: SettingsCard, SettingsExpander, Expander, Control, Layout, Settings
|
||||
dev_langs:
|
||||
- csharp
|
||||
category: Controls
|
||||
subcategory: Layout
|
||||
discussion-id: 129
|
||||
issue-id: 216
|
||||
icon: Assets/SettingsExpander.png
|
||||
---
|
||||
|
||||
The `SettingsExpander` can be used to group multiple `SettingsCard`s into a single collapsable group.
|
||||
|
||||
A `SettingsExpander` can have it's own content to display a setting on the right, just like a `SettingsCard`, but in addition can have any number of extra `Items` to include as additional settings. These items are `SettingsCard`s themselves, which means you can easily move a setting into or out of Expanders just by cutting and pasting their XAML!
|
||||
|
||||
> [!SAMPLE SettingsExpanderSample]
|
||||
|
||||
You can easily override certain properties to create custom experiences. For instance, you can customize the `ContentAlignment` of a `SettingsCard`, to align your content to the Right (default), Left (hiding the `HeaderIcon`, `Header` and `Description`) or Vertically (usually best paired with changing the `HorizontalContentAlignment` to `Stretch`).
|
||||
|
||||
`SettingsExpander` is also an `ItemsControl`, so its items can be driven by a collection and the `ItemsSource` property. You can use the `ItemTemplate` to define how your data object is represented as a `SettingsCard`, as shown below. The `ItemsHeader` and `ItemsFooter` property can be used to host custom content at the start or end of the items list.
|
||||
|
||||
> [!SAMPLE SettingsExpanderItemsSourceSample]
|
||||
|
||||
NOTE: Due to [a bug](https://github.com/microsoft/microsoft-ui-xaml/issues/3842) related to the `ItemsRepeater` used in `SettingsExpander`, there might be visual glitches whenever the `SettingsExpander` expands and a `MaxWidth` is set on a parent `StackPanel`. As a workaround, the `StackPanel` (that has the `MaxWidth` set) can be wrapped in a `Grid` to overcome this issue. See the `SettingsPageExample` for snippet.
|
|
@ -1,92 +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="SettingsControlsExperiment.Samples.SettingsExpanderItemsSourceSample"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:labs="using:CommunityToolkit.Labs.WinUI"
|
||||
xmlns:local="using:SettingsControlsExperiment.Samples"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
|
||||
mc:Ignorable="d">
|
||||
<Page.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="ms-appx:///CommunityToolkit.Labs.WinUI.SettingsControls/SettingsExpander/SettingsExpander.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</Page.Resources>
|
||||
<StackPanel Spacing="3">
|
||||
<labs:SettingsExpander Description="The SettingsExpander can use ItemsSource to define its Items."
|
||||
Header="Settings Expander with ItemsSource"
|
||||
ItemsSource="{x:Bind MyDataSet}">
|
||||
<labs:SettingsExpander.HeaderIcon>
|
||||
<FontIcon Glyph="" />
|
||||
</labs:SettingsExpander.HeaderIcon>
|
||||
<labs:SettingsExpander.ItemTemplate>
|
||||
<DataTemplate x:DataType="local:MyDataModel">
|
||||
<labs:SettingsCard Description="{x:Bind Info}"
|
||||
Header="{x:Bind Name}">
|
||||
<HyperlinkButton Content="{x:Bind LinkDescription}"
|
||||
NavigateUri="{x:Bind Url}" />
|
||||
</labs:SettingsCard>
|
||||
</DataTemplate>
|
||||
</labs:SettingsExpander.ItemTemplate>
|
||||
<labs:SettingsExpander.ItemsHeader>
|
||||
<muxc:InfoBar Title="This is the ItemsHeader"
|
||||
BorderThickness="0"
|
||||
CornerRadius="0"
|
||||
IsIconVisible="False"
|
||||
IsOpen="True"
|
||||
Severity="Success">
|
||||
<muxc:InfoBar.ActionButton>
|
||||
<HyperlinkButton Content="It can host custom content" />
|
||||
</muxc:InfoBar.ActionButton>
|
||||
</muxc:InfoBar>
|
||||
</labs:SettingsExpander.ItemsHeader>
|
||||
<labs:SettingsExpander.ItemsFooter>
|
||||
<labs:SettingsCard Header="This is the ItemsFooter"
|
||||
Style="{StaticResource DefaultSettingsExpanderItemStyle}">
|
||||
<Button Content="Add a device" />
|
||||
</labs:SettingsCard>
|
||||
</labs:SettingsExpander.ItemsFooter>
|
||||
</labs:SettingsExpander>
|
||||
|
||||
<labs:SettingsExpander Description="SettingsExpander can use a DataTemplate, DataTemplateSelector, or IElementFactory for its ItemTemplate."
|
||||
Header="Settings Expander with a custom ItemTemplate"
|
||||
ItemsSource="{x:Bind MyDataSet}">
|
||||
<labs:SettingsExpander.HeaderIcon>
|
||||
<FontIcon Glyph="" />
|
||||
</labs:SettingsExpander.HeaderIcon>
|
||||
<labs:SettingsExpander.ItemTemplate>
|
||||
<local:MyDataModelTemplateSelector>
|
||||
<local:MyDataModelTemplateSelector.ButtonTemplate>
|
||||
<DataTemplate x:DataType="local:MyDataModel">
|
||||
<labs:SettingsCard Description="{x:Bind ItemType}"
|
||||
Header="{x:Bind Name}">
|
||||
<Button Click="Button_Click"
|
||||
Content="{x:Bind LinkDescription}" />
|
||||
</labs:SettingsCard>
|
||||
</DataTemplate>
|
||||
</local:MyDataModelTemplateSelector.ButtonTemplate>
|
||||
|
||||
<local:MyDataModelTemplateSelector.LinkButtonTemplate>
|
||||
<DataTemplate x:DataType="local:MyDataModel">
|
||||
<labs:SettingsCard Description="{x:Bind ItemType}"
|
||||
Header="{x:Bind Name}">
|
||||
<HyperlinkButton Content="{x:Bind LinkDescription}"
|
||||
NavigateUri="{x:Bind Url}" />
|
||||
</labs:SettingsCard>
|
||||
</DataTemplate>
|
||||
</local:MyDataModelTemplateSelector.LinkButtonTemplate>
|
||||
|
||||
<local:MyDataModelTemplateSelector.NoButtonTemplate>
|
||||
<DataTemplate x:DataType="local:MyDataModel">
|
||||
<labs:SettingsCard Description="{x:Bind ItemType}"
|
||||
Header="{x:Bind Name}" />
|
||||
</DataTemplate>
|
||||
</local:MyDataModelTemplateSelector.NoButtonTemplate>
|
||||
</local:MyDataModelTemplateSelector>
|
||||
</labs:SettingsExpander.ItemTemplate>
|
||||
</labs:SettingsExpander>
|
||||
</StackPanel>
|
||||
</Page>
|
|
@ -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.
|
||||
|
||||
using Windows.System;
|
||||
|
||||
namespace SettingsControlsExperiment.Samples;
|
||||
|
||||
[ToolkitSample(id: nameof(SettingsExpanderItemsSourceSample), "SettingsExpanderItemsSource", description: "The SettingsExpander can also be filled with items based on a collection.")]
|
||||
public sealed partial class SettingsExpanderItemsSourceSample : Page
|
||||
{
|
||||
|
||||
public ObservableCollection<MyDataModel> MyDataSet = new() {
|
||||
new()
|
||||
{
|
||||
Name = "First Item",
|
||||
Info = "More about first item.",
|
||||
ItemType = "Item type: Button",
|
||||
LinkDescription = "Click here for more on first item.",
|
||||
Url = "https://microsoft.com/",
|
||||
},
|
||||
new()
|
||||
{
|
||||
Name = "Second Item",
|
||||
Info = "More about second item.",
|
||||
ItemType = "Item type: Link button",
|
||||
LinkDescription = "Click here for more on second item.",
|
||||
Url = "https://xbox.com/",
|
||||
},
|
||||
new()
|
||||
{
|
||||
Name = "Third Item",
|
||||
Info = "More about third item.",
|
||||
ItemType = "Item type: No button",
|
||||
LinkDescription = "Click here for more on third item.",
|
||||
Url = "https://toolkitlabs.dev/",
|
||||
},
|
||||
};
|
||||
|
||||
public SettingsExpanderItemsSourceSample()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
|
||||
private async void Button_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
_ = await Launcher.LaunchUriAsync(new("https://microsoft.com/"));
|
||||
}
|
||||
}
|
||||
|
||||
public class MyDataModel
|
||||
{
|
||||
public string? Name { get; set; }
|
||||
|
||||
public string? Info { get; set; }
|
||||
|
||||
public string? ItemType { get; set; }
|
||||
|
||||
public string? LinkDescription { get; set; }
|
||||
|
||||
public string? Url { get; set; }
|
||||
}
|
||||
|
||||
public class MyDataModelTemplateSelector : DataTemplateSelector
|
||||
{
|
||||
public DataTemplate? ButtonTemplate { get; set; }
|
||||
public DataTemplate? LinkButtonTemplate { get; set; }
|
||||
public DataTemplate? NoButtonTemplate { get; set; }
|
||||
|
||||
protected override DataTemplate SelectTemplateCore(object item)
|
||||
{
|
||||
var itm = (MyDataModel)item;
|
||||
if (itm.ItemType?.EndsWith("Button") == true)
|
||||
{
|
||||
return ButtonTemplate!;
|
||||
}
|
||||
else if (itm.ItemType?.EndsWith("Link button") == true)
|
||||
{
|
||||
return LinkButtonTemplate!;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NoButtonTemplate!;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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. -->
|
||||
<Page x:Class="SettingsControlsExperiment.Samples.SettingsExpanderSample"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:labs="using:CommunityToolkit.Labs.WinUI"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<labs:SettingsExpander x:Name="settingsCard"
|
||||
Description="The SettingsExpander has the same properties as a Card, and you can set SettingsCard as part of the Items collection."
|
||||
Header="SettingsExpander"
|
||||
IsEnabled="{x:Bind IsCardEnabled, Mode=OneWay}"
|
||||
IsExpanded="{x:Bind IsCardExpanded, Mode=OneWay}">
|
||||
<!-- TODO: This should be TwoWay bound but throws compile error in Uno. -->
|
||||
<labs:SettingsExpander.HeaderIcon>
|
||||
<FontIcon Glyph="" />
|
||||
</labs:SettingsExpander.HeaderIcon>
|
||||
<ComboBox SelectedIndex="0">
|
||||
<ComboBoxItem>Option 1</ComboBoxItem>
|
||||
<ComboBoxItem>Option 2</ComboBoxItem>
|
||||
<ComboBoxItem>Option 3</ComboBoxItem>
|
||||
</ComboBox>
|
||||
|
||||
<labs:SettingsExpander.Items>
|
||||
<labs:SettingsCard Header="A basic SettingsCard within an SettingsExpander">
|
||||
<Button Content="Button" />
|
||||
</labs:SettingsCard>
|
||||
<labs:SettingsCard Description="SettingsCard within an Expander can be made clickable too!"
|
||||
Header="This item can be clicked"
|
||||
IsClickEnabled="True" />
|
||||
|
||||
<labs:SettingsCard ContentAlignment="Left">
|
||||
<CheckBox Content="Here the ContentAlignment is set to Left. This is great for e.g. CheckBoxes or RadioButtons." />
|
||||
</labs:SettingsCard>
|
||||
|
||||
<labs:SettingsCard HorizontalContentAlignment="Left"
|
||||
ContentAlignment="Vertical"
|
||||
Description="You can also align your content vertically. Make sure to set the HorizontalAlignment to Left when you do!"
|
||||
Header="Vertically aligned">
|
||||
<GridView SelectedIndex="1">
|
||||
<GridViewItem>
|
||||
<Border Width="64"
|
||||
Height="64"
|
||||
Background="#0078D4"
|
||||
CornerRadius="4" />
|
||||
</GridViewItem>
|
||||
<GridViewItem>
|
||||
<Border Width="64"
|
||||
Height="64"
|
||||
Background="#005EB7"
|
||||
CornerRadius="4" />
|
||||
</GridViewItem>
|
||||
<GridViewItem>
|
||||
<Border Width="64"
|
||||
Height="64"
|
||||
Background="#003D92"
|
||||
CornerRadius="4" />
|
||||
</GridViewItem>
|
||||
<GridViewItem>
|
||||
<Border Width="64"
|
||||
Height="64"
|
||||
Background="#001968"
|
||||
CornerRadius="4" />
|
||||
</GridViewItem>
|
||||
</GridView>
|
||||
</labs:SettingsCard>
|
||||
<labs:SettingsCard Description="You can override the Left indention of a SettingsCard by overriding the SettingsCardLeftIndention"
|
||||
Header="Customization">
|
||||
<labs:SettingsCard.Resources>
|
||||
<x:Double x:Key="SettingsCardLeftIndention">40</x:Double>
|
||||
</labs:SettingsCard.Resources>
|
||||
</labs:SettingsCard>
|
||||
</labs:SettingsExpander.Items>
|
||||
</labs:SettingsExpander>
|
||||
</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 SettingsControlsExperiment.Samples;
|
||||
|
||||
[ToolkitSampleBoolOption("IsCardExpanded", false, Title = "Is Expanded")]
|
||||
[ToolkitSampleBoolOption("IsCardEnabled", true, Title = "Is Enabled")]
|
||||
[ToolkitSample(id: nameof(SettingsExpanderSample), "SettingsExpander", description: "The SettingsExpander can be used to group settings. SettingsCards can be customized in terms of alignment and content.")]
|
||||
public sealed partial class SettingsExpanderSample : Page
|
||||
{
|
||||
public SettingsExpanderSample()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
---
|
||||
title: Settings Page Example
|
||||
author: niels9001
|
||||
description: A full example of building a Windows 11 style settings experience with SettingsCard and SettingsExpander.
|
||||
keywords: SettingsCard, SettingsExpander, Example, Control, Layout, Settings
|
||||
dev_langs:
|
||||
- csharp
|
||||
category: Controls
|
||||
subcategory: Layout
|
||||
discussion-id: 129
|
||||
issue-id: 216
|
||||
icon: Assets/SettingsExpander.png
|
||||
---
|
||||
|
||||
> [!SAMPLE SettingsPageExample]
|
|
@ -1,119 +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="SettingsControlsExperiment.Samples.SettingsPageExample"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:labs="using:CommunityToolkit.Labs.WinUI"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:win="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
mc:Ignorable="d">
|
||||
<Page.Resources>
|
||||
<!-- These styles can be referenced to create a consistent SettingsPage layout -->
|
||||
|
||||
<!-- Spacing between cards -->
|
||||
<x:Double x:Key="SettingsCardSpacing">3</x:Double>
|
||||
|
||||
<!-- Style (inc. the correct spacing) of a section header -->
|
||||
<Style x:Key="SettingsSectionHeaderTextBlockStyle"
|
||||
BasedOn="{StaticResource BodyStrongTextBlockStyle}"
|
||||
TargetType="TextBlock">
|
||||
<Style.Setters>
|
||||
<Setter Property="Margin" Value="1,29,0,5" />
|
||||
</Style.Setters>
|
||||
</Style>
|
||||
</Page.Resources>
|
||||
<ScrollViewer>
|
||||
<Grid>
|
||||
<StackPanel MaxWidth="1000"
|
||||
HorizontalAlignment="Stretch"
|
||||
Spacing="{StaticResource SettingsCardSpacing}">
|
||||
<win:StackPanel.ChildrenTransitions>
|
||||
<win:EntranceThemeTransition FromVerticalOffset="50" />
|
||||
<win:RepositionThemeTransition IsStaggeringEnabled="False" />
|
||||
</win:StackPanel.ChildrenTransitions>
|
||||
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}"
|
||||
Text="Section 1" />
|
||||
<labs:SettingsCard Description="This is a default card, with the Header, HeaderIcon, Description and Content set"
|
||||
Header="This is the Header">
|
||||
<labs:SettingsCard.HeaderIcon>
|
||||
<FontIcon Glyph="" />
|
||||
</labs:SettingsCard.HeaderIcon>
|
||||
<ToggleSwitch IsOn="True" />
|
||||
</labs:SettingsCard>
|
||||
|
||||
<labs:SettingsExpander Description="The SettingsExpander has the same properties as a SettingsCard"
|
||||
Header="SettingsExpander">
|
||||
<labs:SettingsExpander.HeaderIcon>
|
||||
<FontIcon Glyph="" />
|
||||
</labs:SettingsExpander.HeaderIcon>
|
||||
<Button Content="Content"
|
||||
Style="{StaticResource AccentButtonStyle}" />
|
||||
|
||||
<labs:SettingsExpander.Items>
|
||||
<labs:SettingsCard Header="A basic SettingsCard within an SettingsExpander">
|
||||
<Button Content="Button" />
|
||||
</labs:SettingsCard>
|
||||
<labs:SettingsCard Description="SettingsCard within an Expander can be made clickable too!"
|
||||
Header="This item can be clicked"
|
||||
IsClickEnabled="True" />
|
||||
|
||||
<labs:SettingsCard ContentAlignment="Left">
|
||||
<CheckBox Content="Here the ContentAlignment is set to Left. This is great for e.g. CheckBoxes or RadioButtons" />
|
||||
</labs:SettingsCard>
|
||||
</labs:SettingsExpander.Items>
|
||||
</labs:SettingsExpander>
|
||||
|
||||
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}"
|
||||
Text="Section 2" />
|
||||
<labs:SettingsCard Description="Another card to show grouping of cards"
|
||||
Header="Another SettingsCard">
|
||||
<labs:SettingsCard.HeaderIcon>
|
||||
<FontIcon Glyph="" />
|
||||
</labs:SettingsCard.HeaderIcon>
|
||||
<ComboBox SelectedIndex="0">
|
||||
<ComboBoxItem>Option 1</ComboBoxItem>
|
||||
<ComboBoxItem>Option 2</ComboBoxItem>
|
||||
<ComboBoxItem>Option 3</ComboBoxItem>
|
||||
</ComboBox>
|
||||
</labs:SettingsCard>
|
||||
|
||||
<labs:SettingsCard Description="Another card to show grouping of cards"
|
||||
Header="Yet another SettingsCard">
|
||||
<labs:SettingsCard.HeaderIcon>
|
||||
<FontIcon Glyph="" />
|
||||
</labs:SettingsCard.HeaderIcon>
|
||||
<Button Content="Content" />
|
||||
</labs:SettingsCard>
|
||||
|
||||
<!-- Example 'About' section -->
|
||||
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}"
|
||||
Text="About" />
|
||||
|
||||
<labs:SettingsExpander Description="© 2023. All rights reserved."
|
||||
Header="Community Toolkit Gallery">
|
||||
<labs:SettingsExpander.HeaderIcon>
|
||||
<BitmapIcon ShowAsMonochrome="False"
|
||||
UriSource="ms-appx:///Assets/AppTitleBar.scale-200.png" />
|
||||
</labs:SettingsExpander.HeaderIcon>
|
||||
<TextBlock win:IsTextSelectionEnabled="True"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Style="{StaticResource CaptionTextBlockStyle}"
|
||||
Text="Version 1.0.0.0" />
|
||||
<labs:SettingsExpander.Items>
|
||||
<labs:SettingsCard HorizontalContentAlignment="Left"
|
||||
ContentAlignment="Left">
|
||||
<StackPanel Margin="-12,0,0,0"
|
||||
Orientation="Vertical">
|
||||
<HyperlinkButton Content="Link 1" />
|
||||
<HyperlinkButton Content="Link 2" />
|
||||
<HyperlinkButton Content="Link 3" />
|
||||
</StackPanel>
|
||||
</labs:SettingsCard>
|
||||
</labs:SettingsExpander.Items>
|
||||
</labs:SettingsExpander>
|
||||
<HyperlinkButton Margin="0,8,0,0"
|
||||
Content="Send feedback" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
</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 SettingsControlsExperiment.Samples;
|
||||
|
||||
[ToolkitSample(id: nameof(SettingsPageExample), "Settings Page Example", description: "A complete settings page example.")]
|
||||
public sealed partial class SettingsPageExample : Page
|
||||
{
|
||||
public SettingsPageExample()
|
||||
{
|
||||
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("SettingsControls.Tests.Uwp")]
|
||||
[assembly: InternalsVisibleTo("SettingsControls.Tests.WinAppSdk")]
|
||||
[assembly: InternalsVisibleTo("CommunityToolkit.Tests.Uwp")]
|
||||
[assembly: InternalsVisibleTo("CommunityToolkit.Tests.WinAppSdk")]
|
|
@ -1,20 +0,0 @@
|
|||
<Project Sdk="MSBuild.Sdk.Extras/3.0.23">
|
||||
<PropertyGroup>
|
||||
<ToolkitComponentName>SettingsControls</ToolkitComponentName>
|
||||
<Description>This package contains the SettingsCard and SettingsExpander controls.</Description>
|
||||
<Version>0.0.18</Version>
|
||||
<LangVersion>10.0</LangVersion>
|
||||
|
||||
<!-- Rns suffix is required for namespaces shared across projects. See https://github.com/CommunityToolkit/Labs-Windows/issues/152 -->
|
||||
<RootNamespace>CommunityToolkit.Labs.WinUI.SettingsControlsRns</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="SettingsExpander\SettingsExpander.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Sets this up as a toolkit component's source project -->
|
||||
<Import Project="$(ToolingDirectory)\ToolkitComponent.SourceProject.props" />
|
||||
</Project>
|
|
@ -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="CommunityToolkit.Uwp.Triggers" Version="8.0.0-beta.1"/>
|
||||
</ItemGroup>
|
||||
|
||||
<!-- WinUI 2 / Uno -->
|
||||
<ItemGroup Condition="'$(IsUno)' == 'true' AND '$(WinUIMajorVersion)' == '2'">
|
||||
<PackageReference Include="CommunityToolkit.Uwp.Triggers" Version="8.0.0-beta.1"/>
|
||||
</ItemGroup>
|
||||
|
||||
<!-- WinUI 3 / WinAppSdk -->
|
||||
<ItemGroup Condition="'$(IsWinAppSdk)' == 'true'">
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Triggers" Version="8.0.0-beta.1"/>
|
||||
</ItemGroup>
|
||||
|
||||
<!-- WinUI 3 / Uno -->
|
||||
<ItemGroup Condition="'$(IsUno)' == 'true' AND '$(WinUIMajorVersion)' == '3'">
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Triggers" Version="8.0.0-beta.1"/>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -1,9 +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;
|
||||
internal static partial class ControlHelpers
|
||||
{
|
||||
internal static bool IsXamlRootAvailable { get; } = Windows.Foundation.Metadata.ApiInformation.IsPropertyPresent("Windows.UI.Xaml.UIElement", "XamlRoot");
|
||||
}
|
|
@ -1,59 +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;
|
||||
|
||||
// Adapted from https://github.com/rudyhuyn/XamlPlus
|
||||
internal static class ResourceDictionaryExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Copies the <see cref="ResourceDictionary"/> provided as a parameter into the calling dictionary, includes overwriting the source location, theme dictionaries, and merged dictionaries.
|
||||
/// </summary>
|
||||
/// <param name="destination">ResourceDictionary to copy values to.</param>
|
||||
/// <param name="source">ResourceDictionary to copy values from.</param>
|
||||
internal static void CopyFrom(this ResourceDictionary destination, ResourceDictionary source)
|
||||
{
|
||||
if (source.Source != null)
|
||||
{
|
||||
destination.Source = source.Source;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Clone theme dictionaries
|
||||
if (source.ThemeDictionaries != null)
|
||||
{
|
||||
foreach (var theme in source.ThemeDictionaries)
|
||||
{
|
||||
if (theme.Value is ResourceDictionary themedResource)
|
||||
{
|
||||
var themeDictionary = new ResourceDictionary();
|
||||
themeDictionary.CopyFrom(themedResource);
|
||||
destination.ThemeDictionaries[theme.Key] = themeDictionary;
|
||||
}
|
||||
else
|
||||
{
|
||||
destination.ThemeDictionaries[theme.Key] = theme.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clone merged dictionaries
|
||||
if (source.MergedDictionaries != null)
|
||||
{
|
||||
foreach (var mergedResource in source.MergedDictionaries)
|
||||
{
|
||||
var themeDictionary = new ResourceDictionary();
|
||||
themeDictionary.CopyFrom(mergedResource);
|
||||
destination.MergedDictionaries.Add(themeDictionary);
|
||||
}
|
||||
}
|
||||
|
||||
// Clone all contents
|
||||
foreach (var item in source)
|
||||
{
|
||||
destination[item.Key] = item.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,73 +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;
|
||||
|
||||
// Adapted from https://github.com/rudyhuyn/XamlPlus
|
||||
public static partial class StyleExtensions
|
||||
{
|
||||
// Used to distinct normal ResourceDictionary and the one we add.
|
||||
private sealed class StyleExtensionResourceDictionary : ResourceDictionary
|
||||
{
|
||||
}
|
||||
|
||||
public static ResourceDictionary GetResources(Style obj)
|
||||
{
|
||||
return (ResourceDictionary)obj.GetValue(ResourcesProperty);
|
||||
}
|
||||
|
||||
public static void SetResources(Style obj, ResourceDictionary value)
|
||||
{
|
||||
obj.SetValue(ResourcesProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ResourcesProperty =
|
||||
DependencyProperty.RegisterAttached("Resources", typeof(ResourceDictionary), typeof(StyleExtensions), new PropertyMetadata(null, ResourcesChanged));
|
||||
|
||||
private static void ResourcesChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
if (!(sender is FrameworkElement frameworkElement))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var mergedDictionaries = frameworkElement.Resources?.MergedDictionaries;
|
||||
if (mergedDictionaries == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var existingResourceDictionary =
|
||||
mergedDictionaries.FirstOrDefault(c => c is StyleExtensionResourceDictionary);
|
||||
if (existingResourceDictionary != null)
|
||||
{
|
||||
// Remove the existing resource dictionary
|
||||
mergedDictionaries.Remove(existingResourceDictionary);
|
||||
}
|
||||
|
||||
if (e.NewValue is ResourceDictionary resource)
|
||||
{
|
||||
var clonedResources = new StyleExtensionResourceDictionary();
|
||||
clonedResources.CopyFrom(resource);
|
||||
mergedDictionaries.Add(clonedResources);
|
||||
}
|
||||
|
||||
if (frameworkElement.IsLoaded)
|
||||
{
|
||||
// Only force if the style was applied after the control was loaded
|
||||
ForceControlToReloadThemeResources(frameworkElement);
|
||||
}
|
||||
}
|
||||
|
||||
private static void ForceControlToReloadThemeResources(FrameworkElement frameworkElement)
|
||||
{
|
||||
// To force the refresh of all resource references.
|
||||
// Note: Doesn't work when in high-contrast.
|
||||
var currentRequestedTheme = frameworkElement.RequestedTheme;
|
||||
frameworkElement.RequestedTheme = currentRequestedTheme == ElementTheme.Dark
|
||||
? ElementTheme.Light
|
||||
: ElementTheme.Dark;
|
||||
frameworkElement.RequestedTheme = currentRequestedTheme;
|
||||
}
|
||||
}
|
|
@ -1,193 +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 SettingsCard : ButtonBase
|
||||
{
|
||||
/// <summary>
|
||||
/// The backing <see cref="DependencyProperty"/> for the <see cref="Header"/> property.
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty HeaderProperty = DependencyProperty.Register(
|
||||
nameof(Header),
|
||||
typeof(object),
|
||||
typeof(SettingsCard),
|
||||
new PropertyMetadata(defaultValue: null, (d, e) => ((SettingsCard)d).OnHeaderPropertyChanged((object)e.OldValue, (object)e.NewValue)));
|
||||
|
||||
/// <summary>
|
||||
/// The backing <see cref="DependencyProperty"/> for the <see cref="Description"/> property.
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty DescriptionProperty = DependencyProperty.Register(
|
||||
nameof(Description),
|
||||
typeof(object),
|
||||
typeof(SettingsCard),
|
||||
new PropertyMetadata(defaultValue: null, (d, e) => ((SettingsCard)d).OnDescriptionPropertyChanged((object)e.OldValue, (object)e.NewValue)));
|
||||
|
||||
/// <summary>
|
||||
/// The backing <see cref="DependencyProperty"/> for the <see cref="HeaderIcon"/> property.
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty HeaderIconProperty = DependencyProperty.Register(
|
||||
nameof(HeaderIcon),
|
||||
typeof(IconElement),
|
||||
typeof(SettingsCard),
|
||||
new PropertyMetadata(defaultValue: null, (d, e) => ((SettingsCard)d).OnHeaderIconPropertyChanged((IconElement)e.OldValue, (IconElement)e.NewValue)));
|
||||
|
||||
/// <summary>
|
||||
/// The backing <see cref="DependencyProperty"/> for the <see cref="ActionIcon"/> property.
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty ActionIconProperty = DependencyProperty.Register(
|
||||
nameof(ActionIcon),
|
||||
typeof(IconElement),
|
||||
typeof(SettingsCard),
|
||||
new PropertyMetadata(defaultValue: "\ue974"));
|
||||
|
||||
/// <summary>
|
||||
/// The backing <see cref="DependencyProperty"/> for the <see cref="ActionIconToolTip"/> property.
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty ActionIconToolTipProperty = DependencyProperty.Register(
|
||||
nameof(ActionIconToolTip),
|
||||
typeof(string),
|
||||
typeof(SettingsCard),
|
||||
new PropertyMetadata(defaultValue: "More"));
|
||||
|
||||
/// <summary>
|
||||
/// The backing <see cref="DependencyProperty"/> for the <see cref="IsClickEnabled"/> property.
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty IsClickEnabledProperty = DependencyProperty.Register(
|
||||
nameof(IsClickEnabled),
|
||||
typeof(bool),
|
||||
typeof(SettingsCard),
|
||||
new PropertyMetadata(defaultValue: false, (d, e) => ((SettingsCard)d).OnIsClickEnabledPropertyChanged((bool)e.OldValue, (bool)e.NewValue)));
|
||||
|
||||
/// <summary>
|
||||
/// The backing <see cref="DependencyProperty"/> for the <see cref="ContentAlignment"/> property.
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty ContentAlignmentProperty = DependencyProperty.Register(
|
||||
nameof(ContentAlignment),
|
||||
typeof(ContentAlignment),
|
||||
typeof(SettingsCard),
|
||||
new PropertyMetadata(defaultValue: ContentAlignment.Right));
|
||||
|
||||
/// <summary>
|
||||
/// The backing <see cref="DependencyProperty"/> for the <see cref="IsActionIconVisible"/> property.
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty IsActionIconVisibleProperty = DependencyProperty.Register(
|
||||
nameof(IsActionIconVisible),
|
||||
typeof(bool),
|
||||
typeof(SettingsCard),
|
||||
new PropertyMetadata(defaultValue: true, (d, e) => ((SettingsCard)d).OnIsActionIconVisiblePropertyChanged((bool)e.OldValue, (bool)e.NewValue)));
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Header.
|
||||
/// </summary>
|
||||
public object Header
|
||||
{
|
||||
get => (object)GetValue(HeaderProperty);
|
||||
set => SetValue(HeaderProperty, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the description.
|
||||
/// </summary>
|
||||
#pragma warning disable CS0109 // Member does not hide an inherited member; new keyword is not required
|
||||
public new object Description
|
||||
#pragma warning restore CS0109 // Member does not hide an inherited member; new keyword is not required
|
||||
{
|
||||
get => (object)GetValue(DescriptionProperty);
|
||||
set => SetValue(DescriptionProperty, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the icon on the left.
|
||||
/// </summary>
|
||||
public IconElement HeaderIcon
|
||||
{
|
||||
get => (IconElement)GetValue(HeaderIconProperty);
|
||||
set => SetValue(HeaderIconProperty, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the icon that is shown when IsClickEnabled is set to true.
|
||||
/// </summary>
|
||||
public IconElement ActionIcon
|
||||
{
|
||||
get => (IconElement)GetValue(ActionIconProperty);
|
||||
set => SetValue(ActionIconProperty, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the tooltip of the ActionIcon.
|
||||
/// </summary>
|
||||
public string ActionIconToolTip
|
||||
{
|
||||
get => (string)GetValue(ActionIconToolTipProperty);
|
||||
set => SetValue(ActionIconToolTipProperty, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets if the card can be clicked.
|
||||
/// </summary>
|
||||
public bool IsClickEnabled
|
||||
{
|
||||
get => (bool)GetValue(IsClickEnabledProperty);
|
||||
set => SetValue(IsClickEnabledProperty, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the alignment of the Content
|
||||
/// </summary>
|
||||
public ContentAlignment ContentAlignment
|
||||
{
|
||||
get => (ContentAlignment)GetValue(ContentAlignmentProperty);
|
||||
set => SetValue(ContentAlignmentProperty, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets if the ActionIcon is shown.
|
||||
/// </summary>
|
||||
public bool IsActionIconVisible
|
||||
{
|
||||
get => (bool)GetValue(IsActionIconVisibleProperty);
|
||||
set => SetValue(IsActionIconVisibleProperty, value);
|
||||
}
|
||||
|
||||
protected virtual void OnIsClickEnabledPropertyChanged(bool oldValue, bool newValue)
|
||||
{
|
||||
OnIsClickEnabledChanged();
|
||||
}
|
||||
protected virtual void OnHeaderIconPropertyChanged(IconElement oldValue, IconElement newValue)
|
||||
{
|
||||
OnHeaderIconChanged();
|
||||
}
|
||||
|
||||
protected virtual void OnHeaderPropertyChanged(object oldValue, object newValue)
|
||||
{
|
||||
OnHeaderChanged();
|
||||
}
|
||||
|
||||
protected virtual void OnDescriptionPropertyChanged(object oldValue, object newValue)
|
||||
{
|
||||
OnDescriptionChanged();
|
||||
}
|
||||
|
||||
protected virtual void OnIsActionIconVisiblePropertyChanged(bool oldValue, bool newValue)
|
||||
{
|
||||
OnActionIconChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public enum ContentAlignment
|
||||
{
|
||||
/// <summary>
|
||||
/// The Content is aligned to the right. Default state.
|
||||
/// </summary>
|
||||
Right,
|
||||
/// <summary>
|
||||
/// The Content is left-aligned while the Header, HeaderIcon and Description are collapsed. This is commonly used for Content types such as CheckBoxes, RadioButtons and custom layouts.
|
||||
/// </summary>
|
||||
Left,
|
||||
/// <summary>
|
||||
/// The Content is vertically aligned.
|
||||
/// </summary>
|
||||
Vertical
|
||||
}
|
|
@ -1,233 +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>
|
||||
/// This is the base control to create consistent settings experiences, inline with the Windows 11 design language.
|
||||
/// A SettingsCard can also be hosted within a SettingsExpander.
|
||||
/// </summary>
|
||||
|
||||
[TemplatePart(Name = ActionIconPresenterHolder, Type = typeof(Viewbox))]
|
||||
[TemplatePart(Name = HeaderPresenter, Type = typeof(ContentPresenter))]
|
||||
[TemplatePart(Name = DescriptionPresenter, Type = typeof(ContentPresenter))]
|
||||
[TemplatePart(Name = HeaderIconPresenterHolder, Type = typeof(Viewbox))]
|
||||
public partial class SettingsCard : ButtonBase
|
||||
{
|
||||
internal const string NormalState = "Normal";
|
||||
internal const string PointerOverState = "PointerOver";
|
||||
internal const string PressedState = "Pressed";
|
||||
internal const string DisabledState = "Disabled";
|
||||
|
||||
internal const string ActionIconPresenterHolder = "PART_ActionIconPresenterHolder";
|
||||
internal const string HeaderPresenter = "PART_HeaderPresenter";
|
||||
internal const string DescriptionPresenter = "PART_DescriptionPresenter";
|
||||
internal const string HeaderIconPresenterHolder = "PART_HeaderIconPresenterHolder";
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="SettingsCard"/> class.
|
||||
/// </summary>
|
||||
public SettingsCard()
|
||||
{
|
||||
this.DefaultStyleKey = typeof(SettingsCard);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void OnApplyTemplate()
|
||||
{
|
||||
base.OnApplyTemplate();
|
||||
IsEnabledChanged -= OnIsEnabledChanged;
|
||||
OnActionIconChanged();
|
||||
OnHeaderChanged();
|
||||
OnHeaderIconChanged();
|
||||
OnDescriptionChanged();
|
||||
OnIsClickEnabledChanged();
|
||||
VisualStateManager.GoToState(this, IsEnabled ? NormalState : DisabledState, true);
|
||||
RegisterAutomation();
|
||||
IsEnabledChanged += OnIsEnabledChanged;
|
||||
}
|
||||
|
||||
private void RegisterAutomation()
|
||||
{
|
||||
if (Header is string headerString && headerString != string.Empty)
|
||||
{
|
||||
AutomationProperties.SetName(this, headerString);
|
||||
// We don't want to override an AutomationProperties.Name that is manually set, or if the Content basetype is of type ButtonBase (the ButtonBase.Content will be used then)
|
||||
if (Content is UIElement element && string.IsNullOrEmpty(AutomationProperties.GetName(element)) && element.GetType().BaseType != typeof(ButtonBase) && element.GetType() != typeof(TextBlock))
|
||||
{
|
||||
AutomationProperties.SetName(element, headerString);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void EnableButtonInteraction()
|
||||
{
|
||||
DisableButtonInteraction();
|
||||
|
||||
IsTabStop = true;
|
||||
PointerEntered += Control_PointerEntered;
|
||||
PointerExited += Control_PointerExited;
|
||||
PointerCaptureLost += Control_PointerCaptureLost;
|
||||
PointerCanceled += Control_PointerCanceled;
|
||||
PreviewKeyDown += Control_PreviewKeyDown;
|
||||
PreviewKeyUp += Control_PreviewKeyUp;
|
||||
}
|
||||
|
||||
private void DisableButtonInteraction()
|
||||
{
|
||||
IsTabStop = false;
|
||||
PointerEntered -= Control_PointerEntered;
|
||||
PointerExited -= Control_PointerExited;
|
||||
PointerCaptureLost -= Control_PointerCaptureLost;
|
||||
PointerCanceled -= Control_PointerCanceled;
|
||||
PreviewKeyDown -= Control_PreviewKeyDown;
|
||||
PreviewKeyUp -= Control_PreviewKeyUp;
|
||||
}
|
||||
|
||||
private void Control_PreviewKeyUp(object sender, KeyRoutedEventArgs e)
|
||||
{
|
||||
if (e.Key == Windows.System.VirtualKey.Enter || e.Key == Windows.System.VirtualKey.Space || e.Key == Windows.System.VirtualKey.GamepadA)
|
||||
{
|
||||
VisualStateManager.GoToState(this, NormalState, true);
|
||||
}
|
||||
}
|
||||
|
||||
private void Control_PreviewKeyDown(object sender, KeyRoutedEventArgs e)
|
||||
{
|
||||
if (e.Key == Windows.System.VirtualKey.Enter || e.Key == Windows.System.VirtualKey.Space || e.Key == Windows.System.VirtualKey.GamepadA)
|
||||
{
|
||||
// Check if the active focus is on the card itself - only then we show the pressed state.
|
||||
if (GetFocusedElement() is SettingsCard)
|
||||
{
|
||||
VisualStateManager.GoToState(this, PressedState, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Control_PointerEntered(object sender, PointerRoutedEventArgs e)
|
||||
{
|
||||
base.OnPointerEntered(e);
|
||||
VisualStateManager.GoToState(this, PointerOverState, true);
|
||||
}
|
||||
|
||||
public void Control_PointerExited(object sender, PointerRoutedEventArgs e)
|
||||
{
|
||||
base.OnPointerExited(e);
|
||||
VisualStateManager.GoToState(this, NormalState, true);
|
||||
}
|
||||
|
||||
private void Control_PointerCaptureLost(object sender, PointerRoutedEventArgs e)
|
||||
{
|
||||
base.OnPointerCaptureLost(e);
|
||||
VisualStateManager.GoToState(this, NormalState, true);
|
||||
}
|
||||
|
||||
private void Control_PointerCanceled(object sender, PointerRoutedEventArgs e)
|
||||
{
|
||||
base.OnPointerCanceled(e);
|
||||
VisualStateManager.GoToState(this, NormalState, true);
|
||||
}
|
||||
|
||||
protected override void OnPointerPressed(PointerRoutedEventArgs e)
|
||||
{
|
||||
// e.Handled = true;
|
||||
if (IsClickEnabled)
|
||||
{
|
||||
base.OnPointerPressed(e);
|
||||
VisualStateManager.GoToState(this, PressedState, true);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnPointerReleased(PointerRoutedEventArgs e)
|
||||
{
|
||||
if (IsClickEnabled)
|
||||
{
|
||||
base.OnPointerReleased(e);
|
||||
VisualStateManager.GoToState(this, NormalState, true);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates AutomationPeer
|
||||
/// </summary>
|
||||
/// <returns>An automation peer for <see cref="SettingsCard"/>.</returns>
|
||||
protected override AutomationPeer OnCreateAutomationPeer()
|
||||
{
|
||||
return new SettingsCardAutomationPeer(this);
|
||||
}
|
||||
|
||||
private void OnIsClickEnabledChanged()
|
||||
{
|
||||
OnActionIconChanged();
|
||||
if (IsClickEnabled)
|
||||
{
|
||||
EnableButtonInteraction();
|
||||
}
|
||||
else
|
||||
{
|
||||
DisableButtonInteraction();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnIsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
VisualStateManager.GoToState(this, IsEnabled ? NormalState : DisabledState, true);
|
||||
}
|
||||
|
||||
private void OnActionIconChanged()
|
||||
{
|
||||
if (GetTemplateChild(ActionIconPresenterHolder) is FrameworkElement actionIconPresenter)
|
||||
{
|
||||
if (IsClickEnabled && IsActionIconVisible)
|
||||
{
|
||||
actionIconPresenter.Visibility = Visibility.Visible;
|
||||
}
|
||||
else
|
||||
{
|
||||
actionIconPresenter.Visibility =Visibility.Collapsed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnHeaderIconChanged()
|
||||
{
|
||||
if (GetTemplateChild(HeaderIconPresenterHolder) is FrameworkElement headerIconPresenter)
|
||||
{
|
||||
headerIconPresenter.Visibility = HeaderIcon != null
|
||||
? Visibility.Visible
|
||||
: Visibility.Collapsed;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDescriptionChanged()
|
||||
{
|
||||
if (GetTemplateChild(DescriptionPresenter) is FrameworkElement descriptionPresenter)
|
||||
{
|
||||
descriptionPresenter.Visibility = Description != null
|
||||
? Visibility.Visible
|
||||
: Visibility.Collapsed;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnHeaderChanged()
|
||||
{
|
||||
if (GetTemplateChild(HeaderPresenter) is FrameworkElement headerPresenter)
|
||||
{
|
||||
headerPresenter.Visibility = Header != null
|
||||
? Visibility.Visible
|
||||
: Visibility.Collapsed;
|
||||
}
|
||||
}
|
||||
|
||||
private FrameworkElement? GetFocusedElement()
|
||||
{
|
||||
if (ControlHelpers.IsXamlRootAvailable && XamlRoot != null)
|
||||
{
|
||||
return FocusManager.GetFocusedElement(XamlRoot) as FrameworkElement;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FocusManager.GetFocusedElement() as FrameworkElement;
|
||||
}
|
||||
}
|
||||
}
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,47 +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;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace CommunityToolkit.Labs.WinUI;
|
||||
|
||||
/// <summary>
|
||||
/// AutomationPeer for SettingsCard
|
||||
/// </summary>
|
||||
public class SettingsCardAutomationPeer : FrameworkElementAutomationPeer
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SettingsCard"/> class.
|
||||
/// </summary>
|
||||
/// <param name="owner">SettingsCard</param>
|
||||
public SettingsCardAutomationPeer(SettingsCard owner)
|
||||
: base(owner)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the control type for the element that is associated with the UI Automation peer.
|
||||
/// </summary>
|
||||
/// <returns>The control type.</returns>
|
||||
protected override AutomationControlType GetAutomationControlTypeCore()
|
||||
{
|
||||
return AutomationControlType.Group;
|
||||
}
|
||||
|
||||
/// <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()
|
||||
{
|
||||
string classNameCore = Owner.GetType().Name;
|
||||
#if DEBUG_AUTOMATION
|
||||
System.Diagnostics.Debug.WriteLine("SettingsCardAutomationPeer.GetClassNameCore returns " + classNameCore);
|
||||
#endif
|
||||
return classNameCore;
|
||||
}
|
||||
}
|
|
@ -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 CommunityToolkit.Labs.WinUI;
|
||||
public partial class SettingsExpander
|
||||
{
|
||||
/// <summary>
|
||||
/// Fires when the SettingsExpander is opened
|
||||
/// </summary>
|
||||
public event EventHandler? Expanded;
|
||||
|
||||
/// <summary>
|
||||
/// Fires when the expander is closed
|
||||
/// </summary>
|
||||
public event EventHandler? Collapsed;
|
||||
}
|
|
@ -1,70 +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;
|
||||
|
||||
//// Implement properties for ItemsControl like behavior.
|
||||
public partial class SettingsExpander
|
||||
{
|
||||
public IList<object> Items
|
||||
{
|
||||
get { return (IList<object>)GetValue(ItemsProperty); }
|
||||
set { SetValue(ItemsProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ItemsProperty =
|
||||
DependencyProperty.Register(nameof(Items), typeof(IList<object>), typeof(SettingsExpander), new PropertyMetadata(null, OnItemsConnectedPropertyChanged));
|
||||
|
||||
public object ItemsSource
|
||||
{
|
||||
get { return (object)GetValue(ItemsSourceProperty); }
|
||||
set { SetValue(ItemsSourceProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ItemsSourceProperty =
|
||||
DependencyProperty.Register(nameof(ItemsSource), typeof(object), typeof(SettingsExpander), new PropertyMetadata(null, OnItemsConnectedPropertyChanged));
|
||||
|
||||
public object ItemTemplate
|
||||
{
|
||||
get { return (object)GetValue(ItemTemplateProperty); }
|
||||
set { SetValue(ItemTemplateProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ItemTemplateProperty =
|
||||
DependencyProperty.Register(nameof(ItemTemplate), typeof(object), typeof(SettingsExpander), new PropertyMetadata(null));
|
||||
|
||||
public StyleSelector ItemContainerStyleSelector
|
||||
{
|
||||
get { return (StyleSelector)GetValue(ItemContainerStyleSelectorProperty); }
|
||||
set { SetValue(ItemContainerStyleSelectorProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ItemContainerStyleSelectorProperty =
|
||||
DependencyProperty.Register(nameof(ItemContainerStyleSelector), typeof(StyleSelector), typeof(SettingsExpander), new PropertyMetadata(null));
|
||||
|
||||
private static void OnItemsConnectedPropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs args)
|
||||
{
|
||||
if (dependencyObject is SettingsExpander expander && expander._itemsRepeater is not null)
|
||||
{
|
||||
var datasource = expander.ItemsSource;
|
||||
|
||||
if (datasource is null)
|
||||
{
|
||||
datasource = expander.Items;
|
||||
}
|
||||
|
||||
expander._itemsRepeater.ItemsSource = datasource;
|
||||
}
|
||||
}
|
||||
|
||||
private void ItemsRepeater_ElementPrepared(MUXC.ItemsRepeater sender, MUXC.ItemsRepeaterElementPreparedEventArgs args)
|
||||
{
|
||||
if (ItemContainerStyleSelector != null &&
|
||||
args.Element is FrameworkElement element &&
|
||||
element.ReadLocalValue(FrameworkElement.StyleProperty) == DependencyProperty.UnsetValue)
|
||||
{
|
||||
// TODO: Get item from args.Index?
|
||||
element.Style = ItemContainerStyleSelector.SelectStyle(null, element);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,153 +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;
|
||||
|
||||
[ContentProperty(Name = nameof(Content))]
|
||||
public partial class SettingsExpander
|
||||
{
|
||||
/// <summary>
|
||||
/// The backing <see cref="DependencyProperty"/> for the <see cref="Header"/> property.
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty HeaderProperty = DependencyProperty.Register(
|
||||
nameof(Header),
|
||||
typeof(object),
|
||||
typeof(SettingsExpander),
|
||||
new PropertyMetadata(defaultValue: null));
|
||||
|
||||
/// <summary>
|
||||
/// The backing <see cref="DependencyProperty"/> for the <see cref="Description"/> property.
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty DescriptionProperty = DependencyProperty.Register(
|
||||
nameof(Description),
|
||||
typeof(object),
|
||||
typeof(SettingsExpander),
|
||||
new PropertyMetadata(defaultValue: null));
|
||||
|
||||
/// <summary>
|
||||
/// The backing <see cref="DependencyProperty"/> for the <see cref="HeaderIcon"/> property.
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty HeaderIconProperty = DependencyProperty.Register(
|
||||
nameof(HeaderIcon),
|
||||
typeof(IconElement),
|
||||
typeof(SettingsExpander),
|
||||
new PropertyMetadata(defaultValue: null));
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The backing <see cref="DependencyProperty"/> for the <see cref="Content"/> property.
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty ContentProperty = DependencyProperty.Register(
|
||||
nameof(Content),
|
||||
typeof(object),
|
||||
typeof(SettingsExpander),
|
||||
new PropertyMetadata(defaultValue: null));
|
||||
|
||||
/// <summary>
|
||||
/// The backing <see cref="DependencyProperty"/> for the <see cref="Content"/> property.
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty ItemsHeaderProperty = DependencyProperty.Register(
|
||||
nameof(ItemsHeader),
|
||||
typeof(UIElement),
|
||||
typeof(SettingsExpander),
|
||||
new PropertyMetadata(defaultValue: null));
|
||||
|
||||
/// <summary>
|
||||
/// The backing <see cref="DependencyProperty"/> for the <see cref="Content"/> property.
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty ItemsFooterProperty = DependencyProperty.Register(
|
||||
nameof(ItemsFooter),
|
||||
typeof(UIElement),
|
||||
typeof(SettingsExpander),
|
||||
new PropertyMetadata(defaultValue: null));
|
||||
|
||||
/// <summary>
|
||||
/// The backing <see cref="DependencyProperty"/> for the <see cref="IsExpanded"/> property.
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty IsExpandedProperty = DependencyProperty.Register(
|
||||
nameof(IsExpanded),
|
||||
typeof(bool),
|
||||
typeof(SettingsExpander),
|
||||
new PropertyMetadata(defaultValue: false, (d, e) => ((SettingsExpander)d).OnIsExpandedPropertyChanged((bool)e.OldValue, (bool)e.NewValue)));
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// <summary>
|
||||
/// Gets or sets the Header.
|
||||
/// </summary>
|
||||
public object Header
|
||||
{
|
||||
get => (object)GetValue(HeaderProperty);
|
||||
set => SetValue(HeaderProperty, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Description.
|
||||
/// </summary>
|
||||
#pragma warning disable CS0109 // Member does not hide an inherited member; new keyword is not required
|
||||
public new object Description
|
||||
#pragma warning restore CS0109 // Member does not hide an inherited member; new keyword is not required
|
||||
{
|
||||
get => (object)GetValue(DescriptionProperty);
|
||||
set => SetValue(DescriptionProperty, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the HeaderIcon.
|
||||
/// </summary>
|
||||
public IconElement HeaderIcon
|
||||
{
|
||||
get => (IconElement)GetValue(HeaderIconProperty);
|
||||
set => SetValue(HeaderIconProperty, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Content.
|
||||
/// </summary>
|
||||
public object Content
|
||||
{
|
||||
get => (object)GetValue(ContentProperty);
|
||||
set => SetValue(ContentProperty, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the ItemsFooter.
|
||||
/// </summary>
|
||||
public UIElement ItemsHeader
|
||||
{
|
||||
get => (UIElement)GetValue(ItemsHeaderProperty);
|
||||
set => SetValue(ItemsHeaderProperty, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the ItemsFooter.
|
||||
/// </summary>
|
||||
public UIElement ItemsFooter
|
||||
{
|
||||
get => (UIElement)GetValue(ItemsFooterProperty);
|
||||
set => SetValue(ItemsFooterProperty, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the IsExpanded state.
|
||||
/// </summary>
|
||||
public bool IsExpanded
|
||||
{
|
||||
get => (bool)GetValue(IsExpandedProperty);
|
||||
set => SetValue(IsExpandedProperty, value);
|
||||
}
|
||||
protected virtual void OnIsExpandedPropertyChanged(bool oldValue, bool newValue)
|
||||
{
|
||||
OnIsExpandedChanged(oldValue, newValue);
|
||||
|
||||
if (newValue)
|
||||
{
|
||||
Expanded?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
else
|
||||
{
|
||||
Collapsed?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,71 +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;
|
||||
|
||||
//// Note: ItemsRepeater will request all the available horizontal space: https://github.com/microsoft/microsoft-ui-xaml/issues/3842
|
||||
[TemplatePart(Name = PART_ItemsRepeater, Type = typeof(MUXC.ItemsRepeater))]
|
||||
public partial class SettingsExpander : Control
|
||||
{
|
||||
private const string PART_ItemsRepeater = "PART_ItemsRepeater";
|
||||
|
||||
private MUXC.ItemsRepeater? _itemsRepeater;
|
||||
|
||||
/// <summary>
|
||||
/// The SettingsExpander is a collapsable control to host multiple SettingsCards.
|
||||
/// </summary>
|
||||
public SettingsExpander()
|
||||
{
|
||||
this.DefaultStyleKey = typeof(SettingsExpander);
|
||||
Items = new List<object>();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void OnApplyTemplate()
|
||||
{
|
||||
base.OnApplyTemplate();
|
||||
RegisterAutomation();
|
||||
|
||||
if (_itemsRepeater != null)
|
||||
{
|
||||
_itemsRepeater.ElementPrepared -= this.ItemsRepeater_ElementPrepared;
|
||||
}
|
||||
|
||||
_itemsRepeater = GetTemplateChild(PART_ItemsRepeater) as MUXC.ItemsRepeater;
|
||||
|
||||
if (_itemsRepeater != null)
|
||||
{
|
||||
_itemsRepeater.ElementPrepared += this.ItemsRepeater_ElementPrepared;
|
||||
|
||||
// Update it's source based on our current items properties.
|
||||
OnItemsConnectedPropertyChanged(this, null!); // Can't get it to accept type here? (DependencyPropertyChangedEventArgs)EventArgs.Empty
|
||||
}
|
||||
}
|
||||
|
||||
private void RegisterAutomation()
|
||||
{
|
||||
if (Header is string headerString && headerString != string.Empty)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(headerString) && string.IsNullOrEmpty(AutomationProperties.GetName(this)))
|
||||
{
|
||||
AutomationProperties.SetName(this, headerString);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates AutomationPeer
|
||||
/// </summary>
|
||||
/// <returns>An automation peer for <see cref="SettingsExpander"/>.</returns>
|
||||
protected override AutomationPeer OnCreateAutomationPeer()
|
||||
{
|
||||
return new SettingsExpanderAutomationPeer(this);
|
||||
}
|
||||
|
||||
private void OnIsExpandedChanged(bool oldValue, bool newValue)
|
||||
{
|
||||
var peer = FrameworkElementAutomationPeer.FromElement(this) as SettingsExpanderAutomationPeer;
|
||||
peer?.RaiseExpandedChangedEvent(newValue);
|
||||
}
|
||||
}
|
|
@ -1,578 +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:animatedvisuals="using:Microsoft.UI.Xaml.Controls.AnimatedVisuals"
|
||||
xmlns:labs="using:CommunityToolkit.Labs.WinUI"
|
||||
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
|
||||
xmlns:win="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
|
||||
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="ms-appx:///CommunityToolkit.Labs.WinUI.SettingsControls/SettingsCard/SettingsCard.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
|
||||
<x:String x:Key="SettingsExpanderChevronToolTip">Show all settings</x:String>
|
||||
<Thickness x:Key="SettingsExpanderHeaderPadding">16,16,4,16</Thickness>
|
||||
<Thickness x:Key="SettingsExpanderItemPadding">58,8,44,8</Thickness>
|
||||
<Thickness x:Key="SettingsExpanderItemBorderThickness">0,1,0,0</Thickness>
|
||||
<Thickness x:Key="ClickableSettingsExpanderItemPadding">58,8,16,8</Thickness>
|
||||
<x:Double x:Key="SettingsExpanderContentMinHeight">16</x:Double>
|
||||
<x:Double x:Key="SettingsExpanderChevronButtonWidth">32</x:Double>
|
||||
<x:Double x:Key="SettingsExpanderChevronButtonHeight">32</x:Double>
|
||||
|
||||
<Style x:Key="DefaultSettingsExpanderItemStyle"
|
||||
BasedOn="{StaticResource DefaultSettingsCardStyle}"
|
||||
TargetType="labs:SettingsCard">
|
||||
<Style.Setters>
|
||||
<Setter Property="BorderThickness" Value="{ThemeResource SettingsExpanderItemBorderThickness}" />
|
||||
<Setter Property="MinHeight" Value="52" />
|
||||
<Setter Property="Padding" Value="{ThemeResource SettingsExpanderItemPadding}" />
|
||||
<Setter Property="CornerRadius" Value="0" />
|
||||
</Style.Setters>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="ClickableSettingsExpanderItemStyle"
|
||||
BasedOn="{StaticResource DefaultSettingsExpanderItemStyle}"
|
||||
TargetType="labs:SettingsCard">
|
||||
<Style.Setters>
|
||||
<Setter Property="Padding" Value="{ThemeResource ClickableSettingsExpanderItemPadding}" />
|
||||
</Style.Setters>
|
||||
</Style>
|
||||
|
||||
<labs:SettingsExpanderItemStyleSelector x:Key="SettingsExpanderItemStyleSelector"
|
||||
ClickableStyle="{StaticResource ClickableSettingsExpanderItemStyle}"
|
||||
DefaultStyle="{StaticResource DefaultSettingsExpanderItemStyle}" />
|
||||
|
||||
<!-- Implicitly applied default style -->
|
||||
<Style BasedOn="{StaticResource DefaultSettingsExpanderStyle}"
|
||||
TargetType="labs:SettingsExpander" />
|
||||
|
||||
<Style x:Key="DefaultSettingsExpanderStyle"
|
||||
TargetType="labs:SettingsExpander">
|
||||
<Style.Setters>
|
||||
<Setter Property="Background" Value="{ThemeResource SettingsCardBackground}" />
|
||||
<Setter Property="Foreground" Value="{ThemeResource SettingsCardForeground}" />
|
||||
<Setter Property="BorderBrush" Value="{ThemeResource SettingsCardBorderBrush}" />
|
||||
<Setter Property="BorderThickness" Value="{ThemeResource SettingsCardBorderThickness}" />
|
||||
<Setter Property="CornerRadius" Value="{ThemeResource ControlCornerRadius}" />
|
||||
<Setter Property="MinHeight" Value="{ThemeResource SettingsCardMinHeight}" />
|
||||
<Setter Property="MinWidth" Value="{ThemeResource SettingsCardMinWidth}" />
|
||||
<Setter Property="IsTabStop" Value="False" />
|
||||
<Setter Property="HorizontalAlignment" Value="Stretch" />
|
||||
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
<Setter Property="BackgroundSizing" Value="InnerBorderEdge" />
|
||||
<Setter Property="Padding" Value="{ThemeResource SettingsExpanderHeaderPadding}" />
|
||||
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
|
||||
<Setter Property="FontWeight" Value="Normal" />
|
||||
<Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}" />
|
||||
<Setter Property="UseSystemFocusVisuals" Value="{StaticResource UseSystemFocusVisuals}" />
|
||||
<Setter Property="ItemContainerStyleSelector" Value="{StaticResource SettingsExpanderItemStyleSelector}" />
|
||||
<Setter Property="FocusVisualMargin" Value="-3" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="labs:SettingsExpander">
|
||||
<muxc:Expander MinWidth="{TemplateBinding MinWidth}"
|
||||
MinHeight="{TemplateBinding MinHeight}"
|
||||
HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
|
||||
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
win:AutomationProperties.HelpText="{TemplateBinding AutomationProperties.HelpText}"
|
||||
win:AutomationProperties.Name="{TemplateBinding AutomationProperties.Name}"
|
||||
IsExpanded="{Binding IsExpanded, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
Style="{StaticResource SettingsExpanderExpanderStyle}">
|
||||
<muxc:Expander.Header>
|
||||
<labs:SettingsCard Padding="{StaticResource SettingsExpanderHeaderPadding}"
|
||||
VerticalAlignment="Center"
|
||||
Background="Transparent"
|
||||
BorderThickness="0"
|
||||
Content="{TemplateBinding Content}"
|
||||
Description="{TemplateBinding Description}"
|
||||
Header="{TemplateBinding Header}"
|
||||
HeaderIcon="{TemplateBinding HeaderIcon}"
|
||||
IsClickEnabled="False" />
|
||||
</muxc:Expander.Header>
|
||||
<muxc:Expander.Content>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<ContentPresenter Content="{TemplateBinding ItemsHeader}" />
|
||||
<muxc:ItemsRepeater x:Name="PART_ItemsRepeater"
|
||||
Grid.Row="1"
|
||||
ItemTemplate="{Binding ItemTemplate, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
TabFocusNavigation="Local">
|
||||
<muxc:ItemsRepeater.Layout>
|
||||
<muxc:StackLayout Orientation="Vertical" />
|
||||
</muxc:ItemsRepeater.Layout>
|
||||
</muxc:ItemsRepeater>
|
||||
<ContentPresenter Grid.Row="2"
|
||||
Content="{TemplateBinding ItemsFooter}" />
|
||||
</Grid>
|
||||
</muxc:Expander.Content>
|
||||
</muxc:Expander>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style.Setters>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="SettingsExpanderExpanderStyle"
|
||||
TargetType="muxc:Expander">
|
||||
<Setter Property="Background" Value="{ThemeResource ExpanderContentBackground}" />
|
||||
<Setter Property="BackgroundSizing" Value="InnerBorderEdge" />
|
||||
<Setter Property="MinWidth" Value="{ThemeResource FlyoutThemeMinWidth}" />
|
||||
<Setter Property="MinHeight" Value="{StaticResource ExpanderMinHeight}" />
|
||||
<Setter Property="BorderThickness" Value="{ThemeResource ExpanderContentDownBorderThickness}" />
|
||||
<Setter Property="BorderBrush" Value="{ThemeResource ExpanderContentBorderBrush}" />
|
||||
<Setter Property="Padding" Value="0" />
|
||||
<Setter Property="HorizontalAlignment" Value="Left" />
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
<Setter Property="CornerRadius" Value="{ThemeResource ControlCornerRadius}" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="muxc:Expander">
|
||||
<Grid MinWidth="{TemplateBinding MinWidth}"
|
||||
MaxWidth="{TemplateBinding MaxWidth}">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition x:Name="Row0"
|
||||
Height="Auto" />
|
||||
<RowDefinition x:Name="Row1"
|
||||
Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup x:Name="ExpandStates">
|
||||
<VisualState x:Name="ExpandUp">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="ExpanderHeader.CornerRadius" Value="{Binding CornerRadius, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource BottomCornerRadiusFilterConverter}}" />
|
||||
</VisualState.Setters>
|
||||
<VisualState.Storyboard>
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ExpanderContent"
|
||||
Storyboard.TargetProperty="Visibility">
|
||||
<DiscreteObjectKeyFrame KeyTime="0"
|
||||
Value="Visible" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="ExpanderContent"
|
||||
Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateY)">
|
||||
<DiscreteDoubleKeyFrame KeyTime="0"
|
||||
Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.ContentHeight}" />
|
||||
<SplineDoubleKeyFrame KeySpline="0.0, 0.0, 0.0, 1.0"
|
||||
KeyTime="0:0:0.333"
|
||||
Value="0" />
|
||||
</DoubleAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualState.Storyboard>
|
||||
</VisualState>
|
||||
<VisualState x:Name="CollapseDown">
|
||||
<VisualState.Storyboard>
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ExpanderContent"
|
||||
Storyboard.TargetProperty="Visibility">
|
||||
<DiscreteObjectKeyFrame KeyTime="0:0:0.2"
|
||||
Value="Collapsed" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="ExpanderContent"
|
||||
Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateY)">
|
||||
<DiscreteDoubleKeyFrame KeyTime="0"
|
||||
Value="0" />
|
||||
<SplineDoubleKeyFrame KeySpline="1.0, 1.0, 0.0, 1.0"
|
||||
KeyTime="0:0:0.167"
|
||||
Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.ContentHeight}" />
|
||||
</DoubleAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualState.Storyboard>
|
||||
</VisualState>
|
||||
<VisualState x:Name="ExpandDown">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="ExpanderHeader.CornerRadius" Value="{Binding CornerRadius, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource TopCornerRadiusFilterConverter}}" />
|
||||
</VisualState.Setters>
|
||||
<VisualState.Storyboard>
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ExpanderContent"
|
||||
Storyboard.TargetProperty="Visibility">
|
||||
<DiscreteObjectKeyFrame KeyTime="0"
|
||||
Value="Visible" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="ExpanderContent"
|
||||
Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateY)">
|
||||
<DiscreteDoubleKeyFrame KeyTime="0"
|
||||
Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.NegativeContentHeight}" />
|
||||
<SplineDoubleKeyFrame KeySpline="0.0, 0.0, 0.0, 1.0"
|
||||
KeyTime="0:0:0.333"
|
||||
Value="0" />
|
||||
</DoubleAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualState.Storyboard>
|
||||
</VisualState>
|
||||
<VisualState x:Name="CollapseUp">
|
||||
<VisualState.Storyboard>
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ExpanderContent"
|
||||
Storyboard.TargetProperty="Visibility">
|
||||
<DiscreteObjectKeyFrame KeyTime="0:0:0.167"
|
||||
Value="Collapsed" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="ExpanderContent"
|
||||
Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateY)">
|
||||
<DiscreteDoubleKeyFrame KeyTime="0"
|
||||
Value="0" />
|
||||
<SplineDoubleKeyFrame KeySpline="1.0, 1.0, 0.0, 1.0"
|
||||
KeyTime="0:0:0.167"
|
||||
Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.NegativeContentHeight}" />
|
||||
</DoubleAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualState.Storyboard>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
<VisualStateGroup x:Name="ExpandDirectionStates">
|
||||
<VisualState x:Name="Down" />
|
||||
<VisualState x:Name="Up">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="ExpanderHeader.Style" Value="{StaticResource ExpanderHeaderUpStyle}" />
|
||||
<Setter Target="ExpanderContent.BorderThickness" Value="{StaticResource ExpanderContentUpBorderThickness}" />
|
||||
<Setter Target="ExpanderContent.CornerRadius" Value="{Binding CornerRadius, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource TopCornerRadiusFilterConverter}}" />
|
||||
<Setter Target="ExpanderHeader.(Grid.Row)" Value="1" />
|
||||
<Setter Target="ExpanderContentClip.(Grid.Row)" Value="0" />
|
||||
<Setter Target="Row0.Height" Value="*" />
|
||||
<Setter Target="Row1.Height" Value="Auto" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
<ToggleButton x:Name="ExpanderHeader"
|
||||
MinHeight="{TemplateBinding MinHeight}"
|
||||
Padding="{StaticResource ExpanderHeaderPadding}"
|
||||
HorizontalAlignment="Stretch"
|
||||
HorizontalContentAlignment="{StaticResource ExpanderHeaderHorizontalContentAlignment}"
|
||||
VerticalContentAlignment="{StaticResource ExpanderHeaderVerticalContentAlignment}"
|
||||
win:AutomationProperties.AutomationId="ExpanderToggleButton"
|
||||
win:AutomationProperties.Name="{TemplateBinding AutomationProperties.Name}"
|
||||
BackgroundSizing="{TemplateBinding BackgroundSizing}"
|
||||
BorderBrush="{ThemeResource ExpanderHeaderBorderBrush}"
|
||||
BorderThickness="{ThemeResource ExpanderHeaderBorderThickness}"
|
||||
Content="{TemplateBinding Header}"
|
||||
ContentTemplate="{TemplateBinding HeaderTemplate}"
|
||||
ContentTemplateSelector="{TemplateBinding HeaderTemplateSelector}"
|
||||
CornerRadius="{TemplateBinding CornerRadius}"
|
||||
IsChecked="{Binding Path=IsExpanded, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
IsEnabled="{TemplateBinding IsEnabled}"
|
||||
IsTabStop="True"
|
||||
Style="{StaticResource SettingsExpanderHeaderDownStyle}" />
|
||||
<!-- The clip is a composition clip applied in code -->
|
||||
<Border x:Name="ExpanderContentClip"
|
||||
Grid.Row="1">
|
||||
<Border x:Name="ExpanderContent"
|
||||
MinHeight="{ThemeResource SettingsExpanderContentMinHeight}"
|
||||
Padding="{TemplateBinding Padding}"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
BackgroundSizing="{TemplateBinding BackgroundSizing}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{StaticResource ExpanderContentDownBorderThickness}"
|
||||
CornerRadius="{Binding CornerRadius, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource BottomCornerRadiusFilterConverter}}"
|
||||
Visibility="Collapsed">
|
||||
<ContentPresenter Margin="0,-2,0,0"
|
||||
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
Content="{TemplateBinding Content}"
|
||||
ContentTemplate="{TemplateBinding ContentTemplate}"
|
||||
ContentTemplateSelector="{TemplateBinding ContentTemplateSelector}" />
|
||||
<Border.RenderTransform>
|
||||
<CompositeTransform />
|
||||
</Border.RenderTransform>
|
||||
</Border>
|
||||
</Border>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="SettingsExpanderHeaderDownStyle"
|
||||
TargetType="ToggleButton">
|
||||
<Setter Property="Padding" Value="0" />
|
||||
<Setter Property="HorizontalContentAlignment" Value="Left" />
|
||||
<Setter Property="BackgroundSizing" Value="InnerBorderEdge" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="ToggleButton">
|
||||
<Grid x:Name="ToggleButtonGrid"
|
||||
Width="{TemplateBinding Width}"
|
||||
MinWidth="{TemplateBinding MinWidth}"
|
||||
MinHeight="{TemplateBinding MinHeight}"
|
||||
MaxWidth="{TemplateBinding MaxWidth}"
|
||||
HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
|
||||
Background="{TemplateBinding Background}"
|
||||
BackgroundSizing="{TemplateBinding BackgroundSizing}"
|
||||
BorderBrush="{ThemeResource ExpanderHeaderBorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
CornerRadius="{TemplateBinding CornerRadius}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal">
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
|
||||
Storyboard.TargetProperty="Foreground">
|
||||
<DiscreteObjectKeyFrame KeyTime="0"
|
||||
Value="{ThemeResource ExpanderHeaderForeground}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ToggleButtonGrid"
|
||||
Storyboard.TargetProperty="BorderBrush">
|
||||
<DiscreteObjectKeyFrame KeyTime="0"
|
||||
Value="{ThemeResource SettingsCardBorderBrush}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ExpandCollapseChevron"
|
||||
Storyboard.TargetProperty="Foreground">
|
||||
<DiscreteObjectKeyFrame KeyTime="0"
|
||||
Value="{ThemeResource ExpanderChevronForeground}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ToggleButtonGrid"
|
||||
Storyboard.TargetProperty="Background">
|
||||
<DiscreteObjectKeyFrame KeyTime="0"
|
||||
Value="{ThemeResource SettingsCardBackground}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
<VisualState x:Name="PointerOver">
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
|
||||
Storyboard.TargetProperty="Foreground">
|
||||
<DiscreteObjectKeyFrame KeyTime="0"
|
||||
Value="{ThemeResource ExpanderHeaderForegroundPointerOver}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ToggleButtonGrid"
|
||||
Storyboard.TargetProperty="BorderBrush">
|
||||
<DiscreteObjectKeyFrame KeyTime="0"
|
||||
Value="{ThemeResource SettingsCardBorderBrushPointerOver}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ExpandCollapseChevron"
|
||||
Storyboard.TargetProperty="Foreground">
|
||||
<DiscreteObjectKeyFrame KeyTime="0"
|
||||
Value="{ThemeResource ExpanderChevronPointerOverForeground}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ToggleButtonGrid"
|
||||
Storyboard.TargetProperty="Background">
|
||||
<DiscreteObjectKeyFrame KeyTime="0"
|
||||
Value="{ThemeResource SettingsCardBackgroundPointerOver}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
<VisualState.Setters>
|
||||
<Setter Target="ExpandCollapseChevron.(muxc:AnimatedIcon.State)" Value="PointerOverOff" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="Pressed">
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
|
||||
Storyboard.TargetProperty="Foreground">
|
||||
<DiscreteObjectKeyFrame KeyTime="0"
|
||||
Value="{ThemeResource ExpanderHeaderForegroundPressed}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ToggleButtonGrid"
|
||||
Storyboard.TargetProperty="BorderBrush">
|
||||
<DiscreteObjectKeyFrame KeyTime="0"
|
||||
Value="{ThemeResource SettingsCardBorderBrushPressed}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ExpandCollapseChevron"
|
||||
Storyboard.TargetProperty="Foreground">
|
||||
<DiscreteObjectKeyFrame KeyTime="0"
|
||||
Value="{ThemeResource ExpanderChevronPressedForeground}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ToggleButtonGrid"
|
||||
Storyboard.TargetProperty="Background">
|
||||
<DiscreteObjectKeyFrame KeyTime="0"
|
||||
Value="{ThemeResource SettingsCardBackgroundPressed}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
<VisualState.Setters>
|
||||
<Setter Target="ExpandCollapseChevron.(muxc:AnimatedIcon.State)" Value="PressedOff" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="Disabled">
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
|
||||
Storyboard.TargetProperty="Foreground">
|
||||
<DiscreteObjectKeyFrame KeyTime="0"
|
||||
Value="{ThemeResource ExpanderHeaderDisabledForeground}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ToggleButtonGrid"
|
||||
Storyboard.TargetProperty="BorderBrush">
|
||||
<DiscreteObjectKeyFrame KeyTime="0"
|
||||
Value="{ThemeResource SettingsCardBorderBrushDisabled}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ExpandCollapseChevron"
|
||||
Storyboard.TargetProperty="Foreground">
|
||||
<DiscreteObjectKeyFrame KeyTime="0"
|
||||
Value="{ThemeResource ExpanderHeaderDisabledForeground}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
<VisualState x:Name="Checked">
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
|
||||
Storyboard.TargetProperty="Foreground">
|
||||
<DiscreteObjectKeyFrame KeyTime="0"
|
||||
Value="{ThemeResource ExpanderHeaderForeground}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ExpandCollapseChevron"
|
||||
Storyboard.TargetProperty="Foreground">
|
||||
<DiscreteObjectKeyFrame KeyTime="0"
|
||||
Value="{ThemeResource ExpanderChevronForeground}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ExpandCollapseChevronBorder"
|
||||
Storyboard.TargetProperty="BorderBrush">
|
||||
<DiscreteObjectKeyFrame KeyTime="0"
|
||||
Value="{ThemeResource ExpanderChevronBorderBrush}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ExpandCollapseChevronBorder"
|
||||
Storyboard.TargetProperty="Background">
|
||||
<DiscreteObjectKeyFrame KeyTime="0"
|
||||
Value="{ThemeResource ExpanderChevronBackground}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
<VisualState.Setters>
|
||||
<Setter Target="ExpandCollapseChevron.(muxc:AnimatedIcon.State)" Value="NormalOn" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="CheckedPointerOver">
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
|
||||
Storyboard.TargetProperty="Foreground">
|
||||
<DiscreteObjectKeyFrame KeyTime="0"
|
||||
Value="{ThemeResource ExpanderHeaderForegroundPointerOver}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ExpandCollapseChevron"
|
||||
Storyboard.TargetProperty="Foreground">
|
||||
<DiscreteObjectKeyFrame KeyTime="0"
|
||||
Value="{ThemeResource ExpanderChevronPointerOverForeground}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ToggleButtonGrid"
|
||||
Storyboard.TargetProperty="BorderBrush">
|
||||
<DiscreteObjectKeyFrame KeyTime="0"
|
||||
Value="{ThemeResource SettingsCardBorderBrushPointerOver}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ToggleButtonGrid"
|
||||
Storyboard.TargetProperty="Background">
|
||||
<DiscreteObjectKeyFrame KeyTime="0"
|
||||
Value="{ThemeResource SettingsCardBackgroundPointerOver}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
<VisualState.Setters>
|
||||
<Setter Target="ExpandCollapseChevron.(muxc:AnimatedIcon.State)" Value="PointerOverOn" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="CheckedPressed">
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
|
||||
Storyboard.TargetProperty="Foreground">
|
||||
<DiscreteObjectKeyFrame KeyTime="0"
|
||||
Value="{ThemeResource ExpanderHeaderForegroundPressed}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ExpandCollapseChevron"
|
||||
Storyboard.TargetProperty="Foreground">
|
||||
<DiscreteObjectKeyFrame KeyTime="0"
|
||||
Value="{ThemeResource ExpanderChevronPressedForeground}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ToggleButtonGrid"
|
||||
Storyboard.TargetProperty="BorderBrush">
|
||||
<DiscreteObjectKeyFrame KeyTime="0"
|
||||
Value="{ThemeResource SettingsCardBorderBrushPressed}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ToggleButtonGrid"
|
||||
Storyboard.TargetProperty="Background">
|
||||
<DiscreteObjectKeyFrame KeyTime="0"
|
||||
Value="{ThemeResource SettingsCardBackgroundPressed}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
<VisualState.Setters>
|
||||
<Setter Target="ExpandCollapseChevron.(muxc:AnimatedIcon.State)" Value="PressedOn" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
|
||||
<VisualState x:Name="CheckedDisabled">
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
|
||||
Storyboard.TargetProperty="Foreground">
|
||||
<DiscreteObjectKeyFrame KeyTime="0"
|
||||
Value="{ThemeResource ExpanderHeaderDisabledForeground}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ExpandCollapseChevron"
|
||||
Storyboard.TargetProperty="Foreground">
|
||||
<DiscreteObjectKeyFrame KeyTime="0"
|
||||
Value="{ThemeResource ExpanderHeaderDisabledForeground}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ToggleButtonGrid"
|
||||
Storyboard.TargetProperty="BorderBrush">
|
||||
<DiscreteObjectKeyFrame KeyTime="0"
|
||||
Value="{ThemeResource SettingsCardBorderBrushDisabled}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
</Storyboard>
|
||||
<VisualState.Setters>
|
||||
<Setter Target="ExpandCollapseChevron.(muxc:AnimatedIcon.State)" Value="NormalOn" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="Indeterminate" />
|
||||
<VisualState x:Name="IndeterminatePointerOver" />
|
||||
<VisualState x:Name="IndeterminatePressed" />
|
||||
<VisualState x:Name="IndeterminateDisabled" />
|
||||
</VisualStateGroup>
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
|
||||
<ContentPresenter x:Name="ContentPresenter"
|
||||
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
win:AutomationProperties.AccessibilityView="Raw"
|
||||
Content="{TemplateBinding Content}"
|
||||
ContentTemplate="{TemplateBinding ContentTemplate}"
|
||||
ContentTransitions="{TemplateBinding ContentTransitions}"
|
||||
Foreground="{TemplateBinding Foreground}" />
|
||||
|
||||
<ContentControl x:Name="ExpandCollapseChevronBorder"
|
||||
Grid.Column="1"
|
||||
Width="{StaticResource SettingsExpanderChevronButtonWidth}"
|
||||
Height="{StaticResource SettingsExpanderChevronButtonHeight}"
|
||||
Margin="0,0,8,0"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
HorizontalContentAlignment="Center"
|
||||
VerticalContentAlignment="Center"
|
||||
Background="{ThemeResource ExpanderChevronBackground}"
|
||||
BorderBrush="{ThemeResource ExpanderChevronBorderBrush}"
|
||||
BorderThickness="{ThemeResource ExpanderChevronBorderThickness}"
|
||||
CornerRadius="{ThemeResource ControlCornerRadius}"
|
||||
FocusVisualMargin="-3"
|
||||
IsTabStop="False"
|
||||
ToolTipService.ToolTip="{StaticResource SettingsExpanderChevronToolTip}"
|
||||
UseSystemFocusVisuals="True">
|
||||
<muxc:AnimatedIcon x:Name="ExpandCollapseChevron"
|
||||
Width="16"
|
||||
Height="16"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
muxc:AnimatedIcon.State="NormalOff"
|
||||
win:AutomationProperties.AccessibilityView="Raw"
|
||||
Foreground="{ThemeResource ExpanderChevronForeground}"
|
||||
RenderTransformOrigin="0.5, 0.5">
|
||||
<animatedvisuals:AnimatedChevronUpDownSmallVisualSource />
|
||||
<muxc:AnimatedIcon.FallbackIconSource>
|
||||
<muxc:FontIconSource FontFamily="{StaticResource SymbolThemeFontFamily}"
|
||||
FontSize="16"
|
||||
Glyph="{StaticResource ExpanderChevronDownGlyph}"
|
||||
IsTextScaleFactorEnabled="False" />
|
||||
</muxc:AnimatedIcon.FallbackIconSource>
|
||||
</muxc:AnimatedIcon>
|
||||
</ContentControl>
|
||||
</Grid>
|
||||
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
</ResourceDictionary>
|
|
@ -1,67 +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;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
|
||||
namespace CommunityToolkit.Labs.WinUI;
|
||||
/// <summary>
|
||||
/// AutomationPeer for SettingsExpander
|
||||
/// </summary>
|
||||
public class SettingsExpanderAutomationPeer : FrameworkElementAutomationPeer
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SettingsExpander"/> class.
|
||||
/// </summary>
|
||||
/// <param name="owner">SettingsExpander</param>
|
||||
public SettingsExpanderAutomationPeer(SettingsExpander owner)
|
||||
: base(owner)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the control type for the element that is associated with the UI Automation peer.
|
||||
/// </summary>
|
||||
/// <returns>The control type.</returns>
|
||||
protected override AutomationControlType GetAutomationControlTypeCore()
|
||||
{
|
||||
return AutomationControlType.Group;
|
||||
}
|
||||
|
||||
/// <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()
|
||||
{
|
||||
string classNameCore = Owner.GetType().Name;
|
||||
#if DEBUG_AUTOMATION
|
||||
System.Diagnostics.Debug.WriteLine("SettingsCardAutomationPeer.GetClassNameCore returns " + classNameCore);
|
||||
#endif
|
||||
return classNameCore;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the property changed event for this AutomationPeer for the provided identifier.
|
||||
/// Narrator does not announce this due to: https://github.com/microsoft/microsoft-ui-xaml/issues/3469
|
||||
/// </summary>
|
||||
/// <param name="newValue">New Expanded state</param>
|
||||
public void RaiseExpandedChangedEvent(bool newValue)
|
||||
{
|
||||
ExpandCollapseState newState = (newValue == true) ?
|
||||
ExpandCollapseState.Expanded :
|
||||
ExpandCollapseState.Collapsed;
|
||||
|
||||
ExpandCollapseState oldState = (newState == ExpandCollapseState.Expanded) ?
|
||||
ExpandCollapseState.Collapsed :
|
||||
ExpandCollapseState.Expanded;
|
||||
|
||||
#if !HAS_UNO
|
||||
RaisePropertyChangedEvent(ExpandCollapsePatternIdentifiers.ExpandCollapseStateProperty, oldState, newState);
|
||||
#endif
|
||||
}
|
||||
}
|
|
@ -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.
|
||||
|
||||
namespace CommunityToolkit.Labs.WinUI;
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="StyleSelector"/> used by <see cref="SettingsExpander"/> to choose the proper <see cref="SettingsCard"/> container style (clickable or not).
|
||||
/// </summary>
|
||||
public class SettingsExpanderItemStyleSelector : StyleSelector
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the default <see cref="Style"/>.
|
||||
/// </summary>
|
||||
public Style DefaultStyle { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the <see cref="Style"/> when clickable.
|
||||
/// </summary>
|
||||
public Style ClickableStyle { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SettingsExpanderItemStyleSelector"/> class.
|
||||
/// </summary>
|
||||
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
|
||||
public SettingsExpanderItemStyleSelector()
|
||||
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override Style SelectStyleCore(object item, DependencyObject container)
|
||||
{
|
||||
if (container is SettingsCard card && card.IsClickEnabled)
|
||||
{
|
||||
return ClickableStyle;
|
||||
}
|
||||
else
|
||||
{
|
||||
return DefaultStyle;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:labs="using:CommunityToolkit.Labs.WinUI">
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="ms-appx:///CommunityToolkit.Labs.WinUI.SettingsControls/SettingsCard/SettingsCard.xaml" />
|
||||
<ResourceDictionary Source="ms-appx:///CommunityToolkit.Labs.WinUI.SettingsControls/SettingsExpander/SettingsExpander.xaml" />
|
||||
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
|
@ -1,133 +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;
|
||||
|
||||
namespace SettingsControlsExperiment.Tests;
|
||||
|
||||
[TestClass]
|
||||
public partial class ExampleSettingsControlsTestClass : VisualUITestBase
|
||||
{
|
||||
// If you don't need access to UI objects directly or async code, use this pattern.
|
||||
[TestMethod]
|
||||
public void SimpleSynchronousExampleTest()
|
||||
{
|
||||
var assembly = typeof(SettingsCard).Assembly;
|
||||
var type = assembly.GetType(typeof(SettingsCard).FullName ?? string.Empty);
|
||||
|
||||
Assert.IsNotNull(type, "Could not find SettingsCard type.");
|
||||
Assert.AreEqual(typeof(SettingsCard), type, "Type of SettingsCard does not match expected type.");
|
||||
}
|
||||
|
||||
// If you don't need access to UI objects directly, use this pattern.
|
||||
[TestMethod]
|
||||
public async Task SimpleAsyncExampleTest()
|
||||
{
|
||||
await Task.Delay(250);
|
||||
|
||||
Assert.IsTrue(true);
|
||||
}
|
||||
|
||||
// Example that shows how to check for exception throwing.
|
||||
[TestMethod]
|
||||
public void SimpleExceptionCheckTest()
|
||||
{
|
||||
// If you need to check exceptions occur for invalid inputs, etc...
|
||||
// Use Assert.ThrowsException to limit the scope to where you expect the error to occur.
|
||||
// Otherwise, using the ExpectedException attribute could swallow or
|
||||
// catch other issues in setup code.
|
||||
Assert.ThrowsException<NotImplementedException>(() => throw new NotImplementedException());
|
||||
}
|
||||
|
||||
// The UIThreadTestMethod automatically dispatches to the UI for us to work with UI objects.
|
||||
[UIThreadTestMethod]
|
||||
public void SimpleUIAttributeExampleTest()
|
||||
{
|
||||
var component = new SettingsCard();
|
||||
Assert.IsNotNull(component);
|
||||
}
|
||||
|
||||
// The UIThreadTestMethod can also easily grab a XAML Page for us by passing its type as a parameter.
|
||||
// This lets us actually test a control as it would behave within an actual application.
|
||||
// The page will already be loaded by the time your test is called.
|
||||
[UIThreadTestMethod]
|
||||
public void SimpleUIExamplePageTest(ExampleSettingsControlsTestPage page)
|
||||
{
|
||||
// You can use the Toolkit Visual Tree helpers here to find the component by type or name:
|
||||
//var component = page.FindDescendant<SettingsCard>();
|
||||
|
||||
//Assert.IsNotNull(component);
|
||||
|
||||
var componentByName = page.FindDescendant("SettingsControlsControl");
|
||||
|
||||
Assert.IsNotNull(componentByName);
|
||||
}
|
||||
|
||||
// You can still do async work with a UIThreadTestMethod as well.
|
||||
[UIThreadTestMethod]
|
||||
public async Task SimpleAsyncUIExamplePageTest(ExampleSettingsControlsTestPage page)
|
||||
{
|
||||
// This helper can be used to wait for a rendering pass to complete.
|
||||
await CompositionTargetHelper.ExecuteAfterCompositionRenderingAsync(() => { });
|
||||
|
||||
var component = page.FindDescendant<SettingsCard>();
|
||||
|
||||
Assert.IsNotNull(component);
|
||||
}
|
||||
|
||||
//// ----------------------------- ADVANCED TEST SCENARIOS -----------------------------
|
||||
|
||||
// If you need to use DataRow, you can use this pattern with the UI dispatch still.
|
||||
// Otherwise, checkout the UIThreadTestMethod attribute above.
|
||||
// See https://github.com/CommunityToolkit/Labs-Windows/issues/186
|
||||
[TestMethod]
|
||||
public async Task ComplexAsyncUIExampleTest()
|
||||
{
|
||||
await EnqueueAsync(() =>
|
||||
{
|
||||
var component = new SettingsCard();
|
||||
Assert.IsNotNull(component);
|
||||
});
|
||||
}
|
||||
|
||||
// If you want to load other content not within a XAML page using the UIThreadTestMethod above.
|
||||
// Then you can do that using the Load/UnloadTestContentAsync methods.
|
||||
[TestMethod]
|
||||
public async Task ComplexAsyncLoadUIExampleTest()
|
||||
{
|
||||
await EnqueueAsync(async () =>
|
||||
{
|
||||
var component = new SettingsCard();
|
||||
Assert.IsNotNull(component);
|
||||
Assert.IsFalse(component.IsLoaded);
|
||||
|
||||
await LoadTestContentAsync(component);
|
||||
|
||||
Assert.IsTrue(component.IsLoaded);
|
||||
|
||||
await UnloadTestContentAsync(component);
|
||||
|
||||
Assert.IsFalse(component.IsLoaded);
|
||||
});
|
||||
}
|
||||
|
||||
// You can still use the UIThreadTestMethod to remove the extra layer for the dispatcher as well:
|
||||
[UIThreadTestMethod]
|
||||
public async Task ComplexAsyncLoadUIExampleWithoutDispatcherTest()
|
||||
{
|
||||
var component = new SettingsCard();
|
||||
Assert.IsNotNull(component);
|
||||
Assert.IsFalse(component.IsLoaded);
|
||||
|
||||
await LoadTestContentAsync(component);
|
||||
|
||||
Assert.IsTrue(component.IsLoaded);
|
||||
|
||||
await UnloadTestContentAsync(component);
|
||||
|
||||
Assert.IsFalse(component.IsLoaded);
|
||||
}
|
||||
}
|
|
@ -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. -->
|
||||
<Page x:Class="SettingsControlsExperiment.Tests.ExampleSettingsControlsTestPage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:labs="using:CommunityToolkit.Labs.WinUI"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Grid>
|
||||
<labs:SettingsCard x:Name="SettingsControlsControl" />
|
||||
</Grid>
|
||||
</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 SettingsControlsExperiment.Tests;
|
||||
|
||||
/// <summary>
|
||||
/// An empty page that can be used on its own or navigated to within a Frame.
|
||||
/// </summary>
|
||||
public sealed partial class ExampleSettingsControlsTestPage : Page
|
||||
{
|
||||
public ExampleSettingsControlsTestPage()
|
||||
{
|
||||
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>D5E2CD55-53B4-49F8-8C2C-0CE2D0DF8457</SharedGUID>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Configuration">
|
||||
<Import_RootNamespace>SettingsControlsExperiment.Tests</Import_RootNamespace>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="$(MSBuildThisFileDirectory)ExampleSettingsControlsTestClass.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)ExampleSettingsControlsTestPage.xaml.cs">
|
||||
<DependentUpon>ExampleSettingsControlsTestPage.xaml</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Include="$(MSBuildThisFileDirectory)ExampleSettingsControlsTestPage.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>D5E2CD55-53B4-49F8-8C2C-0CE2D0DF8457</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="SettingsControls.Tests.projitems" Label="Shared" />
|
||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.CSharp.targets" />
|
||||
</Project>
|
|
@ -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>
|
Загрузка…
Ссылка в новой задаче