* Add `xunit.runner.visualstudio`

* Fix `MemberData` Requirements

* Remove Xcode Beta, Enable Unit Testing

* Remove Unused Test

* Temporarily Remove ImpliedOrderGridBehavior

`Layout.ChildAdded` event not firing https://github.com/dotnet/maui/issues/3309

* Update azure-pipelines.yml

* Add Windows

* Update azure-pipelines.yml

* Update CommunityToolkit.Maui.Sample.csproj

* Update CommunityToolkit.Maui.Sample.csproj

* Update CommunityToolkit.Maui.Sample.csproj

* Delete CommunityToolkit - Backup.Maui.Sample.csproj

* Update CommunityToolkit.Maui.Sample.csproj

* Update CommunityToolkit.Maui.UnitTests.csproj

* Update CommunityToolkit.Maui.UnitTests.csproj
This commit is contained in:
Brandon Minnick 2021-11-09 08:26:51 -08:00 коммит произвёл GitHub
Родитель fbe7489b3e
Коммит 11f35d5cce
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
20 изменённых файлов: 572 добавлений и 446 удалений

Просмотреть файл

@ -8,7 +8,7 @@ variables:
PathToCommunityToolkitCsproj: 'src/CommunityToolkit.Maui/CommunityToolkit.Maui.csproj'
PathToCommunityToolkitSampleCsproj: 'samples/CommunityToolkit.Maui.Sample/CommunityToolkit.Maui.Sample.csproj'
PathToCommunityToolkitUnitTestCsproj: 'src/CommunityToolkit.Maui.UnitTests/CommunityToolkit.Maui.UnitTests.csproj'
XcodeVersion: '13.0_beta'
XcodeVersion: '13.1'
trigger:
branches:
@ -23,7 +23,7 @@ trigger:
- README.md
pr:
autoCancel: true
autoCancel: 'true'
branches:
include:
- main
@ -47,7 +47,6 @@ jobs:
displayName: 'Install .NET SDK'
inputs:
version: '$(NET_VERSION)'
includePreviewVersions: true
- task: CmdLine@2
displayName: 'Install .NET MAUI workload'
inputs:
@ -105,7 +104,7 @@ jobs:
inputs:
script: |
dotnet build $(PathToCommunityToolkitUnitTestCsproj) -c Release
:: dotnet test $(PathToCommunityToolkitUnitTestCsproj) -c Release
dotnet test $(PathToCommunityToolkitUnitTestCsproj) -c Release
- task: CmdLine@2
displayName: Pack Community Toolkit NuGets
inputs:
@ -130,7 +129,7 @@ jobs:
- job: build_macos
displayName: Build macOS Library
pool:
vmImage: macos-11
vmImage: macos-latest
steps:
# if this is a tagged build, then update the version number
- powershell: |
@ -147,8 +146,7 @@ jobs:
- task: UseDotNet@2
displayName: 'Install .NET SDK'
inputs:
version: $(NET_VERSION)
includePreviewVersions: true
version: $(NET_VERSION)
- task: CmdLine@2
displayName: 'Install .NET MAUI workload'
inputs:
@ -168,13 +166,12 @@ jobs:
displayName: 'Build Community Toolkit Sample'
inputs:
script: 'dotnet build $(PathToCommunityToolkitSampleCsproj) -c Release'
# `dotnet test` does not yet support optional workloads https://github.com/dotnet/sdk/issues/21845#issuecomment-943270826
- task: CmdLine@2
displayName: 'Run Unit Tests'
inputs:
script: |
dotnet build $(PathToCommunityToolkitUnitTestCsproj) -c Release
# dotnet test $(PathToCommunityToolkitUnitTestCsproj) -c Release
dotnet test $(PathToCommunityToolkitUnitTestCsproj) -c Release
- task: CmdLine@2
displayName: 'Pack CommunityToolkit NuGets'
inputs:

Просмотреть файл

@ -1,51 +1,69 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<!-- iOS, Android, MacCatalyst -->
<TargetFrameworks>net6.0-ios;net6.0-android;net6.0-maccatalyst</TargetFrameworks>
<OutputType>Exe</OutputType>
<UseMaui>true</UseMaui>
<SingleProject>true</SingleProject>
<RootNamespace>CommunityToolkit.Maui.Sample</RootNamespace>
<PropertyGroup>
<!-- iOS, Android, MacCatalyst -->
<TargetFrameworks>net6.0-ios;net6.0-android;net6.0-maccatalyst</TargetFrameworks>
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows')) and '$(MSBuildRuntimeType)' == 'Full'">$(TargetFrameworks);net6.0-windows10.0.19041</TargetFrameworks>
<OutputType>Exe</OutputType>
<UseMaui>true</UseMaui>
<SingleProject>true</SingleProject>
<RootNamespace>CommunityToolkit.Maui.Sample</RootNamespace>
<EnablePreviewMsixTooling>true</EnablePreviewMsixTooling>
<!-- Display name -->
<ApplicationTitle>CommunityToolkit.Maui.Sample</ApplicationTitle>
<!-- Display name -->
<ApplicationTitle>CommunityToolkit.Maui.Sample</ApplicationTitle>
<!-- App Identifier -->
<ApplicationId>com.microsoft.CommunityToolkit.Maui.Sample</ApplicationId>
<!-- App Identifier -->
<ApplicationId>com.microsoft.CommunityToolkit.Maui.Sample</ApplicationId>
<!-- Versions -->
<ApplicationVersion>1</ApplicationVersion>
<AndroidVersionCode>1</AndroidVersionCode>
</PropertyGroup>
<!-- Versions -->
<ApplicationVersion>1</ApplicationVersion>
<AndroidVersionCode>1</AndroidVersionCode>
</PropertyGroup>
<ItemGroup>
<!-- App Icon -->
<MauiImage Include="Resources\appicon.svg" ForegroundFile="Resources\appiconfg.svg" IsAppIcon="true" Color="#512BD4" />
<ItemGroup>
<!-- App Icon -->
<MauiImage Include="Resources\appicon.svg" ForegroundFile="Resources\appiconfg.svg" IsAppIcon="true" Color="#512BD4" />
<!-- Splash Screen -->
<MauiSplashScreen Include="Resources\appiconfg.svg" Color="#512BD4" />
<!-- Splash Screen -->
<MauiSplashScreen Include="Resources\appiconfg.svg" Color="#512BD4" />
<!-- Images -->
<MauiImage Include="Resources\Images\*" />
<!-- Images -->
<MauiImage Include="Resources\Images\*" />
<!-- Custom Fonts -->
<MauiFont Include="Resources\Fonts\*" />
</ItemGroup>
<!-- Custom Fonts -->
<MauiFont Include="Resources\Fonts\*" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\CommunityToolkit.Maui\CommunityToolkit.Maui.csproj" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\CommunityToolkit.Maui\CommunityToolkit.Maui.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="CommunityToolkit.Mvvm" Version="7.0.3" />
</ItemGroup>
<PropertyGroup>
<InvariantGlobalization Condition="$(TargetFramework.Contains('-maccatalyst'))">true</InvariantGlobalization>
<RuntimeIdentifier Condition="$(TargetFramework.Contains('-ios'))">iossimulator-x64</RuntimeIdentifier>
<RuntimeIdentifier Condition="$(TargetFramework.Contains('-maccatalyst'))">maccatalyst-x64</RuntimeIdentifier>
<UseInterpreter Condition="$(TargetFramework.Contains('-android'))">False</UseInterpreter>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="CommunityToolkit.Mvvm" Version="7.0.3" />
</ItemGroup>
<PropertyGroup>
<!-- Required for C# Hot Reload -->
<UseInterpreter Condition="'$(Configuration)' == 'Debug'">True</UseInterpreter>
<SupportedOSPlatformVersion Condition="'$(TargetFramework)' == 'net6.0-ios'">14.2</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="'$(TargetFramework)' == 'net6.0-maccatalyst'">14.0</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="'$(TargetFramework)' == 'net6.0-android'">21.0</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$(TargetFramework.Contains('-windows'))">10.0.17763.0</SupportedOSPlatformVersion>
<TargetPlatformMinVersion Condition="$(TargetFramework.Contains('-windows'))">10.0.17763.0</TargetPlatformMinVersion>
</PropertyGroup>
<ItemGroup Condition="$(TargetFramework.Contains('-windows'))">
<!-- Required - WinUI does not yet have buildTransitive for everything -->
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.0.0-preview3" />
<PackageReference Include="Microsoft.Graphics.Win2D" Version="1.0.0.29-preview3" />
</ItemGroup>
<PropertyGroup Condition="$(TargetFramework.Contains('-windows'))">
<OutputType>WinExe</OutputType>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
</PropertyGroup>
</Project>

Просмотреть файл

@ -0,0 +1,8 @@
<maui:MauiWinUIApplication
x:Class="CommunityToolkit.Maui.Sample.Windows.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:maui="using:Microsoft.Maui"
xmlns:local="using:CommunityToolkit.Maui.Sample.Windows">
</maui:MauiWinUIApplication>

Просмотреть файл

@ -0,0 +1,33 @@
using Microsoft.Maui;
using Microsoft.Maui.Hosting;
using Microsoft.UI.Xaml;
using Windows.ApplicationModel;
// To learn more about WinUI, the WinUI project structure,
// and more about our project templates, see: http://aka.ms/winui-project-info.
namespace CommunityToolkit.Maui.Sample.Windows;
/// <summary>
/// Provides application-specific behavior to supplement the default Application class.
/// </summary>
public partial class App : MauiWinUIApplication
{
/// <summary>
/// Initializes the singleton application object. This is the first line of authored code
/// executed, and as such is the logical equivalent of main() or WinMain().
/// </summary>
public App()
{
this.InitializeComponent();
}
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
protected override void OnLaunched(LaunchActivatedEventArgs args)
{
base.OnLaunched(args);
Microsoft.Maui.Essentials.Platform.OnLaunched(args);
}
}

Просмотреть файл

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="utf-8"?>
<Package
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
IgnorableNamespaces="uap rescap">
<Identity
Name="E71AB0A7-18D7-47F1-8F52-55C91EAFA3E8"
Publisher="CN=User Name"
Version="1.0.0.0" />
<Properties>
<DisplayName>CommunityToolkit</DisplayName>
<PublisherDisplayName>Microsoft</PublisherDisplayName>
<Logo>Assets\appiconStoreLogo.png</Logo>
</Properties>
<Dependencies>
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.17763.0" MaxVersionTested="10.0.19041.0" />
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.17763.0" MaxVersionTested="10.0.19041.0" />
</Dependencies>
<Resources>
<Resource Language="x-generate"/>
</Resources>
<Applications>
<Application Id="App"
Executable="$targetnametoken$.exe"
EntryPoint="$targetentrypoint$">
<uap:VisualElements
DisplayName="CommunityToolkit"
Description="CommunityToolkit"
BackgroundColor="transparent"
Square150x150Logo="Assets\appiconMediumTile.png"
Square44x44Logo="Assets\appiconLogo.png">
<uap:DefaultTile
Wide310x150Logo="Assets\appiconWideTile.png"
Square71x71Logo="Assets\appiconSmallTile.png"
Square310x310Logo="Assets\appiconLargeTile.png"
ShortName="Toolkit">
<uap:ShowNameOnTiles>
<uap:ShowOn Tile="square150x150Logo"/>
<uap:ShowOn Tile="wide310x150Logo"/>
</uap:ShowNameOnTiles>
</uap:DefaultTile >
<uap:SplashScreen Image="Assets\appiconfgSplashScreen.png" />
</uap:VisualElements>
</Application>
</Applications>
<Capabilities>
<rescap:Capability Name="runFullTrust" />
</Capabilities>
</Package>

Просмотреть файл

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<assemblyIdentity version="1.0.0.0" name="CommunityToolkit.Maui.Sample.Windows.app"/>
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<!-- The combination of below two tags have the following effect:
1) Per-Monitor for >= Windows 10 Anniversary Update
2) System < Windows 10 Anniversary Update
-->
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/PM</dpiAware>
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2, PerMonitor</dpiAwareness>
</windowsSettings>
</application>
</assembly>

Просмотреть файл

@ -0,0 +1,8 @@
{
"profiles": {
"Windows Machine": {
"commandName": "MsixPackage",
"nativeDebugging": false
}
}
}

Просмотреть файл

@ -1,155 +1,156 @@
using System;
using CommunityToolkit.Maui.Behaviors;
using Microsoft.Maui.Controls;
using Xunit;
#warning ImpliedOrderGridBehavior currently broken by .NET MAUI bug: https://github.com/dotnet/maui/issues/3309
//using System;
//using CommunityToolkit.Maui.Behaviors;
//using Microsoft.Maui.Controls;
//using Xunit;
namespace CommunityToolkit.Maui.UnitTests.Behaviors;
//namespace CommunityToolkit.Maui.UnitTests.Behaviors;
public class ImpliedOrderGridBehavior_Tests : BaseTest
{
[Fact]
public void CorrectRowColumnAssignment()
{
var grid = new Grid();
grid.Behaviors.Add(new ImpliedOrderGridBehavior());
//public class ImpliedOrderGridBehavior_Tests : BaseTest
//{
// [Fact]
// public void CorrectRowColumnAssignment()
// {
// var grid = new Grid();
// grid.Behaviors.Add(new ImpliedOrderGridBehavior());
grid.RowDefinitions.Add(new RowDefinition());
grid.RowDefinitions.Add(new RowDefinition());
grid.RowDefinitions.Add(new RowDefinition());
grid.RowDefinitions.Add(new RowDefinition());
grid.RowDefinitions.Add(new RowDefinition());
// grid.RowDefinitions.Add(new RowDefinition());
// grid.RowDefinitions.Add(new RowDefinition());
// grid.RowDefinitions.Add(new RowDefinition());
// grid.RowDefinitions.Add(new RowDefinition());
// grid.RowDefinitions.Add(new RowDefinition());
grid.ColumnDefinitions.Add(new ColumnDefinition());
grid.ColumnDefinitions.Add(new ColumnDefinition());
grid.ColumnDefinitions.Add(new ColumnDefinition());
// grid.ColumnDefinitions.Add(new ColumnDefinition());
// grid.ColumnDefinitions.Add(new ColumnDefinition());
// grid.ColumnDefinitions.Add(new ColumnDefinition());
// R0C0
AssertExpectedCoordinates(grid, new Label(), 0, 0);
// // R0C0
// AssertExpectedCoordinates(grid, new Label(), 0, 0);
// R0C1
AssertExpectedCoordinates(grid, new Label(), 0, 1);
// // R0C1
// AssertExpectedCoordinates(grid, new Label(), 0, 1);
// R0C2
AssertExpectedCoordinates(grid, new Label(), 0, 2);
// // R0C2
// AssertExpectedCoordinates(grid, new Label(), 0, 2);
// R1C0
var columnSpanLabel = new Label();
Grid.SetColumnSpan(columnSpanLabel, 2);
AssertExpectedCoordinates(grid, columnSpanLabel, 1, 0);
// // R1C0
// var columnSpanLabel = new Label();
// Grid.SetColumnSpan(columnSpanLabel, 2);
// AssertExpectedCoordinates(grid, columnSpanLabel, 1, 0);
// R1C2
AssertExpectedCoordinates(grid, new Label(), 1, 2);
// // R1C2
// AssertExpectedCoordinates(grid, new Label(), 1, 2);
// R2C0
var rowSpanLabel = new Label();
Grid.SetRowSpan(rowSpanLabel, 2);
AssertExpectedCoordinates(grid, rowSpanLabel, 2, 0);
// // R2C0
// var rowSpanLabel = new Label();
// Grid.SetRowSpan(rowSpanLabel, 2);
// AssertExpectedCoordinates(grid, rowSpanLabel, 2, 0);
// R2C1
AssertExpectedCoordinates(grid, new Label(), 2, 1);
// // R2C1
// AssertExpectedCoordinates(grid, new Label(), 2, 1);
// R2C2
AssertExpectedCoordinates(grid, new Label(), 2, 2);
// // R2C2
// AssertExpectedCoordinates(grid, new Label(), 2, 2);
// R3C1
AssertExpectedCoordinates(grid, new Label(), 3, 1);
// // R3C1
// AssertExpectedCoordinates(grid, new Label(), 3, 1);
// R0C0 Manual Assignment
var manualSetToUsedCellLabel = new Label();
Grid.SetRow(manualSetToUsedCellLabel, 0);
Grid.SetColumn(manualSetToUsedCellLabel, 0);
AssertExpectedCoordinates(grid, manualSetToUsedCellLabel, 0, 0);
// // R0C0 Manual Assignment
// var manualSetToUsedCellLabel = new Label();
// Grid.SetRow(manualSetToUsedCellLabel, 0);
// Grid.SetColumn(manualSetToUsedCellLabel, 0);
// AssertExpectedCoordinates(grid, manualSetToUsedCellLabel, 0, 0);
// R3C2
AssertExpectedCoordinates(grid, new Label(), 3, 2);
// // R3C2
// AssertExpectedCoordinates(grid, new Label(), 3, 2);
// R4C1
var manualSetToCellLabel = new Label();
Grid.SetRow(manualSetToCellLabel, 4);
Grid.SetColumn(manualSetToCellLabel, 1);
AssertExpectedCoordinates(grid, manualSetToCellLabel, 4, 1);
// // R4C1
// var manualSetToCellLabel = new Label();
// Grid.SetRow(manualSetToCellLabel, 4);
// Grid.SetColumn(manualSetToCellLabel, 1);
// AssertExpectedCoordinates(grid, manualSetToCellLabel, 4, 1);
// R4C0
AssertExpectedCoordinates(grid, new Label(), 4, 0);
}
// // R4C0
// AssertExpectedCoordinates(grid, new Label(), 4, 0);
// }
[Fact]
public void ThrowsOnManualAssignmentToUsedCell()
{
var grid = CreateExceptionTestGrid();
// [Fact]
// public void ThrowsOnManualAssignmentToUsedCell()
// {
// var grid = CreateExceptionTestGrid();
// R0C0
grid.Children.Add(new Label());
// // R0C0
// grid.Children.Add(new Label());
// Manual R0C)
var throwLabel = new Label();
Grid.SetColumn(throwLabel, 0);
Grid.SetRow(throwLabel, 0);
// // Manual R0C)
// var throwLabel = new Label();
// Grid.SetColumn(throwLabel, 0);
// Grid.SetRow(throwLabel, 0);
Assert.Throws<Exception>(() => grid.Children.Add(throwLabel));
}
// Assert.Throws<Exception>(() => grid.Children.Add(throwLabel));
// }
[Fact]
public void ThrowsOnCellsExceeded()
{
var grid = CreateExceptionTestGrid();
// [Fact]
// public void ThrowsOnCellsExceeded()
// {
// var grid = CreateExceptionTestGrid();
// R0C0
grid.Children.Add(new Label());
// // R0C0
// grid.Children.Add(new Label());
// R0C1
grid.Children.Add(new Label());
// // R0C1
// grid.Children.Add(new Label());
// R1C0
grid.Children.Add(new Label());
// // R1C0
// grid.Children.Add(new Label());
// R1C1
grid.Children.Add(new Label());
// // R1C1
// grid.Children.Add(new Label());
// Throws
Assert.Throws<Exception>(() => grid.Children.Add(new Label()));
}
// // Throws
// Assert.Throws<Exception>(() => grid.Children.Add(new Label()));
// }
[Fact]
public void ThrowsOnSpanExceedsColumns()
{
var grid = CreateExceptionTestGrid();
// [Fact]
// public void ThrowsOnSpanExceedsColumns()
// {
// var grid = CreateExceptionTestGrid();
var throwLabel = new Label();
Grid.SetColumnSpan(throwLabel, 10);
// var throwLabel = new Label();
// Grid.SetColumnSpan(throwLabel, 10);
Assert.Throws<Exception>(() => grid.Children.Add(throwLabel));
}
// Assert.Throws<Exception>(() => grid.Children.Add(throwLabel));
// }
[Fact]
public void ThrowsOnSpanExceedsRows()
{
var grid = CreateExceptionTestGrid();
// [Fact]
// public void ThrowsOnSpanExceedsRows()
// {
// var grid = CreateExceptionTestGrid();
var throwLabel = new Label();
Grid.SetRowSpan(throwLabel, 10);
// var throwLabel = new Label();
// Grid.SetRowSpan(throwLabel, 10);
Assert.Throws<Exception>(() => grid.Children.Add(throwLabel));
}
// Assert.Throws<Exception>(() => grid.Children.Add(throwLabel));
// }
Grid CreateExceptionTestGrid()
{
var grid = new Grid();
grid.Behaviors.Add(new ImpliedOrderGridBehavior { ThrowOnLayoutWarning = true });
// Grid CreateExceptionTestGrid()
// {
// var grid = new Grid();
// grid.Behaviors.Add(new ImpliedOrderGridBehavior { ThrowOnLayoutWarning = true });
grid.RowDefinitions.Add(new RowDefinition());
grid.RowDefinitions.Add(new RowDefinition());
// grid.RowDefinitions.Add(new RowDefinition());
// grid.RowDefinitions.Add(new RowDefinition());
grid.ColumnDefinitions.Add(new ColumnDefinition());
grid.ColumnDefinitions.Add(new ColumnDefinition());
// grid.ColumnDefinitions.Add(new ColumnDefinition());
// grid.ColumnDefinitions.Add(new ColumnDefinition());
return grid;
}
// return grid;
// }
void AssertExpectedCoordinates(Grid grid, View view, int row, int column)
{
grid.Children.Add(view);
Assert.Equal(row, Grid.GetRow(view));
Assert.Equal(column, Grid.GetColumn(view));
}
}
// void AssertExpectedCoordinates(Grid grid, View view, int row, int column)
// {
// grid.Children.Add(view);
// Assert.Equal(row, Grid.GetRow(view));
// Assert.Equal(column, Grid.GetColumn(view));
// }
//}

Просмотреть файл

@ -1,19 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net6.0</TargetFrameworks>
<UseMaui>true</UseMaui>
<IsPackable>false</IsPackable>
</PropertyGroup>
<PropertyGroup>
<TargetFrameworks>net6.0</TargetFrameworks>
<UseMaui>true</UseMaui>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.11.0" />
<PackageReference Include="coverlet.collector" Version="3.1.0" PrivateAssets="all" />
<PackageReference Include="xunit" Version="2.4.1" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0" />
<PackageReference Include="Coverlet.Collector" Version="3.1.0" PrivateAssets="all" />
<PackageReference Include="Xunit" Version="2.4.1" />
<PackageReference Include="Xunit.Runner.VisualStudio" Version="2.4.3" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\CommunityToolkit.Maui\CommunityToolkit.Maui.csproj" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\CommunityToolkit.Maui\CommunityToolkit.Maui.csproj" />
</ItemGroup>
</Project>

Просмотреть файл

@ -8,115 +8,115 @@ namespace CommunityToolkit.Maui.UnitTests.Converters;
public class CompareConverter_Tests : BaseTest
{
public const string TrueTestObject = nameof(TrueTestObject);
public const string FalseTestObject = nameof(FalseTestObject);
public const string TrueTestObject = nameof(TrueTestObject);
public const string FalseTestObject = nameof(FalseTestObject);
static readonly IReadOnlyList<object?[]> testData = new[]
{
new object?[] { 10d, CompareConverter.OperatorType.Greater, 20d, TrueTestObject, FalseTestObject, FalseTestObject },
new object?[] { 10d, CompareConverter.OperatorType.GreaterOrEqual, 20d, TrueTestObject, FalseTestObject, FalseTestObject },
new object?[] { 10d, CompareConverter.OperatorType.Equal, 20d, TrueTestObject, FalseTestObject, FalseTestObject },
new object?[] { 10d, CompareConverter.OperatorType.NotEqual, 20d, TrueTestObject, FalseTestObject, TrueTestObject },
new object?[] { 10d, CompareConverter.OperatorType.Smaller, 20d, TrueTestObject, FalseTestObject, TrueTestObject },
new object?[] { 10d, CompareConverter.OperatorType.SmallerOrEqual, 20d, TrueTestObject, FalseTestObject, TrueTestObject },
public static IReadOnlyList<object?[]> TestData { get; } = new[]
{
new object?[] { 10d, CompareConverter.OperatorType.Greater, 20d, TrueTestObject, FalseTestObject, FalseTestObject },
new object?[] { 10d, CompareConverter.OperatorType.GreaterOrEqual, 20d, TrueTestObject, FalseTestObject, FalseTestObject },
new object?[] { 10d, CompareConverter.OperatorType.Equal, 20d, TrueTestObject, FalseTestObject, FalseTestObject },
new object?[] { 10d, CompareConverter.OperatorType.NotEqual, 20d, TrueTestObject, FalseTestObject, TrueTestObject },
new object?[] { 10d, CompareConverter.OperatorType.Smaller, 20d, TrueTestObject, FalseTestObject, TrueTestObject },
new object?[] { 10d, CompareConverter.OperatorType.SmallerOrEqual, 20d, TrueTestObject, FalseTestObject, TrueTestObject },
new object?[] { 20d, CompareConverter.OperatorType.Greater, 20d, TrueTestObject, FalseTestObject, FalseTestObject },
new object?[] { 20d, CompareConverter.OperatorType.GreaterOrEqual, 20d, TrueTestObject, FalseTestObject, TrueTestObject },
new object?[] { 20d, CompareConverter.OperatorType.Equal, 20d, TrueTestObject, FalseTestObject, TrueTestObject },
new object?[] { 20d, CompareConverter.OperatorType.NotEqual, 20d, TrueTestObject, FalseTestObject, FalseTestObject },
new object?[] { 20d, CompareConverter.OperatorType.Smaller, 20d, TrueTestObject, FalseTestObject, FalseTestObject },
new object?[] { 20d, CompareConverter.OperatorType.SmallerOrEqual, 20d, TrueTestObject, FalseTestObject, TrueTestObject },
new object?[] { 20d, CompareConverter.OperatorType.Greater, 20d, TrueTestObject, FalseTestObject, FalseTestObject },
new object?[] { 20d, CompareConverter.OperatorType.GreaterOrEqual, 20d, TrueTestObject, FalseTestObject, TrueTestObject },
new object?[] { 20d, CompareConverter.OperatorType.Equal, 20d, TrueTestObject, FalseTestObject, TrueTestObject },
new object?[] { 20d, CompareConverter.OperatorType.NotEqual, 20d, TrueTestObject, FalseTestObject, FalseTestObject },
new object?[] { 20d, CompareConverter.OperatorType.Smaller, 20d, TrueTestObject, FalseTestObject, FalseTestObject },
new object?[] { 20d, CompareConverter.OperatorType.SmallerOrEqual, 20d, TrueTestObject, FalseTestObject, TrueTestObject },
new object?[] { 20d, CompareConverter.OperatorType.Greater, 10d, TrueTestObject, FalseTestObject, TrueTestObject },
new object?[] { 20d, CompareConverter.OperatorType.GreaterOrEqual, 10d, TrueTestObject, FalseTestObject, TrueTestObject },
new object?[] { 20d, CompareConverter.OperatorType.Equal, 10d, TrueTestObject, FalseTestObject, FalseTestObject },
new object?[] { 20d, CompareConverter.OperatorType.NotEqual, 10d, TrueTestObject, FalseTestObject, TrueTestObject },
new object?[] { 20d, CompareConverter.OperatorType.Smaller, 10d, TrueTestObject, FalseTestObject, FalseTestObject },
new object?[] { 20d, CompareConverter.OperatorType.SmallerOrEqual, 10d, TrueTestObject, FalseTestObject, FalseTestObject },
new object?[] { 20d, CompareConverter.OperatorType.Greater, 10d, TrueTestObject, FalseTestObject, TrueTestObject },
new object?[] { 20d, CompareConverter.OperatorType.GreaterOrEqual, 10d, TrueTestObject, FalseTestObject, TrueTestObject },
new object?[] { 20d, CompareConverter.OperatorType.Equal, 10d, TrueTestObject, FalseTestObject, FalseTestObject },
new object?[] { 20d, CompareConverter.OperatorType.NotEqual, 10d, TrueTestObject, FalseTestObject, TrueTestObject },
new object?[] { 20d, CompareConverter.OperatorType.Smaller, 10d, TrueTestObject, FalseTestObject, FalseTestObject },
new object?[] { 20d, CompareConverter.OperatorType.SmallerOrEqual, 10d, TrueTestObject, FalseTestObject, FalseTestObject },
new object?[] { 20d, CompareConverter.OperatorType.Greater, 20d, null, null, false },
new object?[] { 20d, CompareConverter.OperatorType.GreaterOrEqual, 20d, null, null, true },
new object?[] { 20d, CompareConverter.OperatorType.Equal, 20d, null, null, true },
new object?[] { 20d, CompareConverter.OperatorType.NotEqual, 20d, null, null, false },
new object?[] { 20d, CompareConverter.OperatorType.Smaller, 20d, null, null, false },
new object?[] { 20d, CompareConverter.OperatorType.SmallerOrEqual, 20d, null, null, true },
new object?[] { 20d, CompareConverter.OperatorType.Greater, 20d, null, null, false },
new object?[] { 20d, CompareConverter.OperatorType.GreaterOrEqual, 20d, null, null, true },
new object?[] { 20d, CompareConverter.OperatorType.Equal, 20d, null, null, true },
new object?[] { 20d, CompareConverter.OperatorType.NotEqual, 20d, null, null, false },
new object?[] { 20d, CompareConverter.OperatorType.Smaller, 20d, null, null, false },
new object?[] { 20d, CompareConverter.OperatorType.SmallerOrEqual, 20d, null, null, true },
new object?[] { 20d, CompareConverter.OperatorType.Greater, 10d, null, null, true },
new object?[] { 20d, CompareConverter.OperatorType.GreaterOrEqual, 10d, null, null, true },
new object?[] { 20d, CompareConverter.OperatorType.Equal, 10d, null, null, false },
new object?[] { 20d, CompareConverter.OperatorType.NotEqual, 10d, null, null, true },
new object?[] { 20d, CompareConverter.OperatorType.Smaller, 10d, null, null, false },
new object?[] { 20d, CompareConverter.OperatorType.SmallerOrEqual, 10d, null, null, false },
new object?[] { 20d, CompareConverter.OperatorType.Greater, 10d, null, null, true },
new object?[] { 20d, CompareConverter.OperatorType.GreaterOrEqual, 10d, null, null, true },
new object?[] { 20d, CompareConverter.OperatorType.Equal, 10d, null, null, false },
new object?[] { 20d, CompareConverter.OperatorType.NotEqual, 10d, null, null, true },
new object?[] { 20d, CompareConverter.OperatorType.Smaller, 10d, null, null, false },
new object?[] { 20d, CompareConverter.OperatorType.SmallerOrEqual, 10d, null, null, false },
new object?[] { 10d, CompareConverter.OperatorType.Greater, 20d, null, null, false },
new object?[] { 10d, CompareConverter.OperatorType.GreaterOrEqual, 20d, null, null, false },
new object?[] { 10d, CompareConverter.OperatorType.Equal, 20d, null, null, false },
new object?[] { 10d, CompareConverter.OperatorType.NotEqual, 20d, null, null, true },
new object?[] { 10d, CompareConverter.OperatorType.Smaller, 20d, null, null, true },
new object?[] { 10d, CompareConverter.OperatorType.SmallerOrEqual, 20d, null, null, true }
};
new object?[] { 10d, CompareConverter.OperatorType.Greater, 20d, null, null, false },
new object?[] { 10d, CompareConverter.OperatorType.GreaterOrEqual, 20d, null, null, false },
new object?[] { 10d, CompareConverter.OperatorType.Equal, 20d, null, null, false },
new object?[] { 10d, CompareConverter.OperatorType.NotEqual, 20d, null, null, true },
new object?[] { 10d, CompareConverter.OperatorType.Smaller, 20d, null, null, true },
new object?[] { 10d, CompareConverter.OperatorType.SmallerOrEqual, 20d, null, null, true }
};
static readonly IReadOnlyList<object?[]> throwArgumenExceptionTestData = new[]
{
new object?[] { new { Name = "Not IComparable" } },
new object?[] { null }
};
public static IReadOnlyList<object?[]> ThrowArgumenExceptionTestData { get; } = new[]
{
new object?[] { new { Name = "Not IComparable" } },
new object?[] { null }
};
[Theory]
[MemberData(nameof(testData))]
public void CompareConverterConvert(IComparable value, CompareConverter.OperatorType comparisonOperator, IComparable comparingValue, object trueObject, object falseObject, object expectedResult)
{
var compareConverter = new CompareConverter
{
TrueObject = trueObject,
FalseObject = falseObject,
ComparisonOperator = comparisonOperator,
ComparingValue = comparingValue
};
[Theory]
[MemberData(nameof(TestData))]
public void CompareConverterConvert(IComparable value, CompareConverter.OperatorType comparisonOperator, IComparable comparingValue, object trueObject, object falseObject, object expectedResult)
{
var compareConverter = new CompareConverter
{
TrueObject = trueObject,
FalseObject = falseObject,
ComparisonOperator = comparisonOperator,
ComparingValue = comparingValue
};
var result = compareConverter.Convert(value, typeof(BoolToObjectConverter_Tests), null!, CultureInfo.CurrentCulture);
Assert.Equal(result, expectedResult);
}
var result = compareConverter.Convert(value, typeof(BoolToObjectConverter_Tests), null!, CultureInfo.CurrentCulture);
Assert.Equal(result, expectedResult);
}
[Theory]
[MemberData(nameof(throwArgumenExceptionTestData))]
public void CompareConverterInValidValuesThrowArgumenException(object value)
{
var compareConverter = new CompareConverter()
{
ComparingValue = 20d
};
[Theory]
[MemberData(nameof(ThrowArgumenExceptionTestData))]
public void CompareConverterInValidValuesThrowArgumenException(object value)
{
var compareConverter = new CompareConverter()
{
ComparingValue = 20d
};
Assert.Throws<ArgumentException>(() => compareConverter.Convert(value, typeof(BoolToObjectConverter_Tests), null!, CultureInfo.CurrentCulture));
}
Assert.Throws<ArgumentException>(() => compareConverter.Convert(value, typeof(BoolToObjectConverter_Tests), null!, CultureInfo.CurrentCulture));
}
[Theory]
[InlineData(20d, null, TrueTestObject, FalseTestObject)]
[InlineData(20d, 20d, TrueTestObject, null)]
[InlineData(20d, 20d, null, FalseTestObject)]
public void CompareConverterInValidValuesThrowArgumentNullException(object value, IComparable comparingValue, object trueObject, object falseObject)
{
var compareConverter = new CompareConverter()
{
ComparingValue = comparingValue,
FalseObject = falseObject,
TrueObject = trueObject
};
[Theory]
[InlineData(20d, null, TrueTestObject, FalseTestObject)]
[InlineData(20d, 20d, TrueTestObject, null)]
[InlineData(20d, 20d, null, FalseTestObject)]
public void CompareConverterInValidValuesThrowArgumentNullException(object value, IComparable comparingValue, object trueObject, object falseObject)
{
var compareConverter = new CompareConverter()
{
ComparingValue = comparingValue,
FalseObject = falseObject,
TrueObject = trueObject
};
Assert.Throws<ArgumentNullException>(() => compareConverter.Convert(value, typeof(BoolToObjectConverter_Tests), null!, CultureInfo.CurrentCulture));
}
Assert.Throws<ArgumentNullException>(() => compareConverter.Convert(value, typeof(BoolToObjectConverter_Tests), null!, CultureInfo.CurrentCulture));
}
[Theory]
[InlineData(20d, (CompareConverter.OperatorType)10, 20d)]
public void CompareConverterInValidValuesThrowArgumentOutOfRangeException(object value, CompareConverter.OperatorType comparisonOperator, IComparable comparingValue)
{
var compareConverter = new CompareConverter
{
ComparisonOperator = comparisonOperator,
ComparingValue = comparingValue
};
[Theory]
[InlineData(20d, (CompareConverter.OperatorType)10, 20d)]
public void CompareConverterInValidValuesThrowArgumentOutOfRangeException(object value, CompareConverter.OperatorType comparisonOperator, IComparable comparingValue)
{
var compareConverter = new CompareConverter
{
ComparisonOperator = comparisonOperator,
ComparingValue = comparingValue
};
Assert.Throws<ArgumentOutOfRangeException>(() => compareConverter.Convert(value, typeof(BoolToObjectConverter_Tests), null!, CultureInfo.CurrentCulture));
}
Assert.Throws<ArgumentOutOfRangeException>(() => compareConverter.Convert(value, typeof(BoolToObjectConverter_Tests), null!, CultureInfo.CurrentCulture));
}
}

Просмотреть файл

@ -17,7 +17,7 @@ public class DateTimeOffsetConverter_Tests : BaseTest
static readonly DateTimeOffset testDateTimeOffsetLocal = new(2020, 08, 25, 13, 37, 00, DateTimeOffset.Now.Offset);
static readonly DateTimeOffset testDateTimeOffsetUtc = new(2020, 08, 25, 13, 37, 00, DateTimeOffset.UtcNow.Offset);
static readonly IReadOnlyList<object[]> data = new[]
public static IReadOnlyList<object[]> Data { get; } = new[]
{
new object[] { testDateTimeOffsetNow, testDateTimeNow },
new object[] { DateTimeOffset.MinValue, DateTime.MinValue },
@ -27,7 +27,7 @@ public class DateTimeOffsetConverter_Tests : BaseTest
new object[] { testDateTimeOffsetUtc, testDateTimeUnspecified },
};
static readonly IReadOnlyList<object[]> dataReverse = new[]
public static IReadOnlyList<object[]> DataReverse { get; } = new[]
{
new object[] { testDateTimeNow, testDateTimeOffsetNow },
new object[] { DateTime.MinValue, DateTimeOffset.MinValue },
@ -38,7 +38,7 @@ public class DateTimeOffsetConverter_Tests : BaseTest
};
[Theory]
[MemberData(nameof(data))]
[MemberData(nameof(Data))]
public void DateTimeOffsetConverter(DateTimeOffset value, DateTime expectedResult)
{
var dateTimeOffsetConverter = new DateTimeOffsetConverter();
@ -50,7 +50,7 @@ public class DateTimeOffsetConverter_Tests : BaseTest
}
[Theory]
[MemberData(nameof(dataReverse))]
[MemberData(nameof(DataReverse))]
public void DateTimeOffsetConverterBack(DateTime value, DateTimeOffset expectedResult)
{
var dateTimeOffsetConverter = new DateTimeOffsetConverter();

Просмотреть файл

@ -9,7 +9,7 @@ namespace CommunityToolkit.Maui.UnitTests.Converters;
public class ListIsNotNullOrEmptyConverter_Tests : BaseTest
{
readonly static IReadOnlyList<object?[]> data = new[]
public static IReadOnlyList<object?[]> Data { get; } = new[]
{
new object[] { new List<string>(), false },
new object[] { new List<string>() { "TestValue" }, true },
@ -18,7 +18,7 @@ public class ListIsNotNullOrEmptyConverter_Tests : BaseTest
};
[Theory]
[MemberData(nameof(data))]
[MemberData(nameof(Data))]
public void ListIsNotNullOrEmptyConverter(object value, bool expectedResult)
{
var listIsNotNullOrEmptyConverter = new ListIsNotNullOrEmptyConverter();

Просмотреть файл

@ -9,7 +9,7 @@ namespace CommunityToolkit.Maui.UnitTests.Converters;
public class ListIsNullOrEmptyConverter_Tests : BaseTest
{
static readonly IReadOnlyList<object?[]> data = new[]
public static IReadOnlyList<object?[]> Data { get; } = new[]
{
new object[] { new List<string>(), true },
new object[] { new List<string>() { "TestValue" }, false },
@ -18,7 +18,7 @@ public class ListIsNullOrEmptyConverter_Tests : BaseTest
};
[Theory]
[MemberData(nameof(data))]
[MemberData(nameof(Data))]
public void ListIsNullOrEmptyConverter(object value, bool expectedResult)
{
var listIstNullOrEmptyConverter = new ListIsNullOrEmptyConverter();

Просмотреть файл

@ -7,43 +7,43 @@ namespace CommunityToolkit.Maui.UnitTests.Converters;
public class ListToStringConverter_Tests : BaseTest
{
static readonly IReadOnlyList<object?[]> testData = new[]
{
new object[] { new string[] { "A", "B", "C" }, "+_+", "A+_+B+_+C" },
new object[] { new string[] { "A", string.Empty, "C" }, ",", "A,C" },
new object?[] { new string?[] { "A", null, "C" }, ",", "A,C" },
new object[] { new string[] { "A" }, ":-:", "A" },
new object[] { Array.Empty<string>(), ",", string.Empty },
new object?[] { null, ",", string.Empty },
new object?[] { new string[] { "A", "B", "C" }, null, "ABC" },
};
public static IReadOnlyList<object?[]> TestData { get; } = new[]
{
new object[] { new string[] { "A", "B", "C" }, "+_+", "A+_+B+_+C" },
new object[] { new string[] { "A", string.Empty, "C" }, ",", "A,C" },
new object?[] { new string?[] { "A", null, "C" }, ",", "A,C" },
new object[] { new string[] { "A" }, ":-:", "A" },
new object[] { Array.Empty<string>(), ",", string.Empty },
new object?[] { null, ",", string.Empty },
new object?[] { new string[] { "A", "B", "C" }, null, "ABC" },
};
[Theory]
[MemberData(nameof(testData))]
public void ListToStringConverter(object value, object parameter, object expectedResult)
{
var listToStringConverter = new ListToStringConverter();
[Theory]
[MemberData(nameof(TestData))]
public void ListToStringConverter(object value, object parameter, object expectedResult)
{
var listToStringConverter = new ListToStringConverter();
var result = listToStringConverter.Convert(value, null, parameter, null);
var result = listToStringConverter.Convert(value, null, parameter, null);
Assert.Equal(result, expectedResult);
}
Assert.Equal(result, expectedResult);
}
[Theory]
[InlineData(0)]
public void InValidConverterValuesThrowArgumenException(object value)
{
var listToStringConverter = new ListToStringConverter();
[Theory]
[InlineData(0)]
public void InValidConverterValuesThrowArgumenException(object value)
{
var listToStringConverter = new ListToStringConverter();
Assert.Throws<ArgumentException>(() => listToStringConverter.Convert(value, null, null, null));
}
Assert.Throws<ArgumentException>(() => listToStringConverter.Convert(value, null, null, null));
}
[Theory]
[InlineData(0)]
public void InValidConverterParametersThrowArgumenException(object parameter)
{
var listToStringConverter = new ListToStringConverter();
[Theory]
[InlineData(0)]
public void InValidConverterParametersThrowArgumenException(object parameter)
{
var listToStringConverter = new ListToStringConverter();
Assert.Throws<ArgumentException>(() => listToStringConverter.Convert(Array.Empty<object>(), null, parameter, null));
}
Assert.Throws<ArgumentException>(() => listToStringConverter.Convert(Array.Empty<object>(), null, parameter, null));
}
}

Просмотреть файл

@ -1,15 +0,0 @@
using System;
using Xunit;
namespace CommunityToolkit.Maui.UnitTests.Converters;
public class MultiConverterParameter_Tests : BaseTest
{
public MultiConverterParameter_Tests()
{
}
[Fact]
public void MultiConverterParameterTest() => throw new NotImplementedException();
}

Просмотреть файл

@ -7,13 +7,13 @@ namespace CommunityToolkit.Maui.UnitTests.Converters;
public class MultiConverter_Tests : BaseTest
{
static readonly IReadOnlyList<object[]> data = new[]
public static IReadOnlyList<object[]> Data { get; } = new[]
{
new object[] { new List<MultiConverterParameter>() { { new MultiConverterParameter() { Value = "Param 1", } }, { new MultiConverterParameter() { Value = "Param 2", } } } },
};
[Theory]
[MemberData(nameof(data))]
[MemberData(nameof(Data))]
public void MultiConverter(object value)
{
var multiConverter = new MultiConverter();

Просмотреть файл

@ -7,7 +7,7 @@ namespace CommunityToolkit.Maui.UnitTests.Converters;
public class StringToListConverter_Tests : BaseTest
{
readonly static IReadOnlyList<object?[]> listData = new[]
public static IReadOnlyList<object?[]> ListData { get; } = new[]
{
new object?[] { "A,B.C;D", new string[] { ",", ".", ";" }, new string[] { "A", "B", "C", "D" } },
new object?[] { "A+_+B+_+C", "+_+", new string[] { "A", "B", "C" } },
@ -20,7 +20,7 @@ public class StringToListConverter_Tests : BaseTest
};
[Theory]
[MemberData(nameof(listData))]
[MemberData(nameof(ListData))]
public void StringToListConverter(object? value, object? parameter, object? expectedResult)
{
var stringToListConverter = new StringToListConverter();

Просмотреть файл

@ -10,7 +10,7 @@ public class TextCaseConverter_Tests : BaseTest
const string test = nameof(test);
const string t = nameof(t);
readonly static IReadOnlyList<object?[]> data = new[]
public static IReadOnlyList<object?[]> Data { get; } = new[]
{
new object?[] { test, TextCaseType.Lower, test },
new object?[] { test, TextCaseType.Upper, "TEST" },
@ -31,7 +31,7 @@ public class TextCaseConverter_Tests : BaseTest
enum MockEnum { Foo, Bar, Baz }
[Theory]
[MemberData(nameof(data))]
[MemberData(nameof(Data))]
[InlineData(null, null, null)]
public void TextCaseConverterWithParameter(object? value, object? comparedValue, object? expectedResult)
{
@ -43,7 +43,7 @@ public class TextCaseConverter_Tests : BaseTest
}
[Theory]
[MemberData(nameof(data))]
[MemberData(nameof(Data))]
public void TextCaseConverterWithExplicitType(object? value, TextCaseType textCaseType, object? expectedResult)
{
var textCaseConverter = new TextCaseConverter

Просмотреть файл

@ -1,137 +1,138 @@
using System;
using System.Linq;
using CommunityToolkit.Maui.Behaviors.Internals;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Controls.Internals;
#warning ImpliedOrderGridBehavior currently broken by .NET MAUI bug: https://github.com/dotnet/maui/issues/3309
//using System;
//using System.Linq;
//using CommunityToolkit.Maui.Behaviors.Internals;
//using Microsoft.Maui.Controls;
//using Microsoft.Maui.Controls.Internals;
namespace CommunityToolkit.Maui.Behaviors;
//namespace CommunityToolkit.Maui.Behaviors;
/// <summary>
/// The <see cref="ImpliedOrderGridBehavior"/> enables you to automatically assign a <see cref="Grid"/> row and column to a view based on the order the view is added to the <see cref="Grid"/>. You only need to setup the row and column definitions and then add children to the <see cref="Grid"/>. You may still assign RowSpan and ColumnSpan to views and their values will be taken into account when assigning a row and column to a view. If a view has a user defined row or column value it will be honored.
/// </summary>
public class ImpliedOrderGridBehavior : BaseBehavior<Grid>
{
bool[][]? usedMatrix;
int rowCount;
int columnCount;
///// <summary>
///// The <see cref="ImpliedOrderGridBehavior"/> enables you to automatically assign a <see cref="Grid"/> row and column to a view based on the order the view is added to the <see cref="Grid"/>. You only need to setup the row and column definitions and then add children to the <see cref="Grid"/>. You may still assign RowSpan and ColumnSpan to views and their values will be taken into account when assigning a row and column to a view. If a view has a user defined row or column value it will be honored.
///// </summary>
//public class ImpliedOrderGridBehavior : BaseBehavior<Grid>
//{
// bool[][]? usedMatrix;
// int rowCount;
// int columnCount;
/// <summary>
/// When set to true, warnings will throw an exception instead of being logged. Defaults to false.
/// </summary>
public bool ThrowOnLayoutWarning { get; set; }
// /// <summary>
// /// When set to true, warnings will throw an exception instead of being logged. Defaults to false.
// /// </summary>
// public bool ThrowOnLayoutWarning { get; set; }
/// <inheritdoc />
protected override void OnAttachedTo(Grid bindable)
{
base.OnAttachedTo(bindable);
// /// <inheritdoc />
// protected override void OnAttachedTo(Grid bindable)
// {
// base.OnAttachedTo(bindable);
bindable.ChildAdded += OnInternalGridChildAdded;
}
// bindable.ChildAdded += OnInternalGridChildAdded;
// }
/// <inheritdoc />
protected override void OnDetachingFrom(Grid bindable)
{
base.OnDetachingFrom(bindable);
// /// <inheritdoc />
// protected override void OnDetachingFrom(Grid bindable)
// {
// base.OnDetachingFrom(bindable);
bindable.ChildAdded -= OnInternalGridChildAdded;
}
// bindable.ChildAdded -= OnInternalGridChildAdded;
// }
void OnInternalGridChildAdded(object? sender, ElementEventArgs e) =>
ProcessElement(e.Element);
// void OnInternalGridChildAdded(object? sender, ElementEventArgs e) =>
// ProcessElement(e.Element);
void LogWarning(string warning)
{
Log.Warning(nameof(ImpliedOrderGridBehavior), warning);
if (ThrowOnLayoutWarning)
throw new Exception(warning);
}
// void LogWarning(string warning)
// {
// Log.Warning(nameof(ImpliedOrderGridBehavior), warning);
// if (ThrowOnLayoutWarning)
// throw new Exception(warning);
// }
bool[][] InitMatrix()
{
ArgumentNullException.ThrowIfNull(View);
// bool[][] InitMatrix()
// {
// ArgumentNullException.ThrowIfNull(View);
rowCount = View.RowDefinitions.Count;
if (rowCount == 0)
rowCount = 1;
// rowCount = View.RowDefinitions.Count;
// if (rowCount == 0)
// rowCount = 1;
columnCount = View.ColumnDefinitions.Count;
if (columnCount == 0)
columnCount = 1;
// columnCount = View.ColumnDefinitions.Count;
// if (columnCount == 0)
// columnCount = 1;
var newMatrix = new bool[rowCount][];
for (var r = 0; r < rowCount; r++)
newMatrix[r] = new bool[columnCount];
// var newMatrix = new bool[rowCount][];
// for (var r = 0; r < rowCount; r++)
// newMatrix[r] = new bool[columnCount];
return newMatrix;
}
// return newMatrix;
// }
void FindNextCell(out int rowIndex, out int columnIndex)
{
usedMatrix ??= InitMatrix();
// void FindNextCell(out int rowIndex, out int columnIndex)
// {
// usedMatrix ??= InitMatrix();
// Find the first available row
var row = usedMatrix.FirstOrDefault(r => r.Any(c => !c));
// // Find the first available row
// var row = usedMatrix.FirstOrDefault(r => r.Any(c => !c));
// If no row is found, set cell to origin and log
if (row == null)
{
LogWarning("Defined cells exceeded.");
rowIndex = Math.Max(rowCount - 1, 0);
columnIndex = Math.Max(columnCount - 1, 0);
return;
}
rowIndex = Array.IndexOf(usedMatrix, row);
// // If no row is found, set cell to origin and log
// if (row == null)
// {
// LogWarning("Defined cells exceeded.");
// rowIndex = Math.Max(rowCount - 1, 0);
// columnIndex = Math.Max(columnCount - 1, 0);
// return;
// }
// rowIndex = Array.IndexOf(usedMatrix, row);
// Find the first available column
columnIndex = Array.IndexOf(row, row.FirstOrDefault(c => !c));
}
// // Find the first available column
// columnIndex = Array.IndexOf(row, row.FirstOrDefault(c => !c));
// }
void UpdateUsedCells(int row, int column, int rowSpan, int columnSpan)
{
var rowEnd = row + rowSpan;
var columnEnd = column + columnSpan;
// void UpdateUsedCells(int row, int column, int rowSpan, int columnSpan)
// {
// var rowEnd = row + rowSpan;
// var columnEnd = column + columnSpan;
if (columnEnd > columnCount)
{
columnEnd = columnCount;
LogWarning($"View at row {row} column {columnEnd} with column span {columnSpan} exceeds the defined grid columns.");
}
// if (columnEnd > columnCount)
// {
// columnEnd = columnCount;
// LogWarning($"View at row {row} column {columnEnd} with column span {columnSpan} exceeds the defined grid columns.");
// }
if (rowEnd > rowCount)
{
rowEnd = rowCount;
LogWarning($"View at row {row} column {columnEnd} with row span {rowSpan} exceeds the defined grid rows.");
}
// if (rowEnd > rowCount)
// {
// rowEnd = rowCount;
// LogWarning($"View at row {row} column {columnEnd} with row span {rowSpan} exceeds the defined grid rows.");
// }
for (var r = row; r < rowEnd; r++)
{
for (var c = column; c < columnEnd; c++)
{
if (usedMatrix?[r][c] ?? throw new NullReferenceException())
LogWarning($"Cell at row {r} column {c} has already been used.");
// for (var r = row; r < rowEnd; r++)
// {
// for (var c = column; c < columnEnd; c++)
// {
// if (usedMatrix?[r][c] ?? throw new NullReferenceException())
// LogWarning($"Cell at row {r} column {c} has already been used.");
usedMatrix[r][c] = true;
}
}
}
// usedMatrix[r][c] = true;
// }
// }
// }
void ProcessElement(BindableObject view)
{
var columnSpan = Grid.GetColumnSpan(view);
var rowSpan = Grid.GetRowSpan(view);
// void ProcessElement(BindableObject view)
// {
// var columnSpan = Grid.GetColumnSpan(view);
// var rowSpan = Grid.GetRowSpan(view);
FindNextCell(out var row, out var column);
// FindNextCell(out var row, out var column);
// Check to see if the user manually assigned a row or column
if (view.IsSet(Grid.ColumnProperty))
column = Grid.GetColumn(view);
if (view.IsSet(Grid.RowProperty))
row = Grid.GetRow(view);
// // Check to see if the user manually assigned a row or column
// if (view.IsSet(Grid.ColumnProperty))
// column = Grid.GetColumn(view);
// if (view.IsSet(Grid.RowProperty))
// row = Grid.GetRow(view);
UpdateUsedCells(row, column, rowSpan, columnSpan);
// UpdateUsedCells(row, column, rowSpan, columnSpan);
// Set attributes
view.SetValue(Grid.ColumnProperty, column);
view.SetValue(Grid.RowProperty, row);
}
}
// // Set attributes
// view.SetValue(Grid.ColumnProperty, column);
// view.SetValue(Grid.RowProperty, row);
// }
//}

Просмотреть файл

@ -3,6 +3,7 @@
<PropertyGroup>
<TargetFrameworks>net6.0;net6.0-ios;net6.0-android;net6.0-maccatalyst</TargetFrameworks>
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows')) and '$(MSBuildRuntimeType)' == 'Full'">$(TargetFrameworks);net6.0-windows10.0.17763.0</TargetFrameworks>
<UseMaui>true</UseMaui>
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
@ -66,8 +67,8 @@
</ItemGroup>
<ItemGroup Condition=" $(TargetFramework.Contains('-windows')) ">
<Compile Include="**\*.uwp.cs" />
<Compile Include="**\*.uwp.*.cs" />
<Compile Include="**\*.windows.cs" />
<Compile Include="**\*.windows.*.cs" />
</ItemGroup>
<ItemGroup Condition=" $(TargetFramework.Contains('-maccatalyst')) ">