Added TaskDialog

This commit is contained in:
TheXamlGuy
2024-10-06 21:15:02 +01:00
parent 434c0634e9
commit 9b59add673
13 changed files with 164 additions and 60 deletions
+26 -26
View File
@@ -9,15 +9,15 @@ public class ContentDialogHandler :
{
public async Task Handle(NavigateEventArgs<ContentDialog> args)
{
if (args.Template is ContentDialog contentDialog)
if (args.Template is ContentDialog dialog)
{
contentDialog.DataContext = args.Content;
dialog.DataContext = args.Content;
async void HandlePrimaryButtonClick(FluentAvalonia.UI.Controls.ContentDialog sender,
FluentAvalonia.UI.Controls.ContentDialogButtonClickEventArgs args)
{
contentDialog.PrimaryButtonClick -= HandlePrimaryButtonClick;
if (contentDialog.DataContext is object content)
dialog.PrimaryButtonClick -= HandlePrimaryButtonClick;
if (dialog.DataContext is object content)
{
if (content is IPrimaryConfirmation primaryConfirmation)
{
@@ -25,7 +25,7 @@ public class ContentDialogHandler :
if (!await primaryConfirmation.ConfirmPrimary())
{
args.Cancel = true;
contentDialog.PrimaryButtonClick += HandlePrimaryButtonClick;
dialog.PrimaryButtonClick += HandlePrimaryButtonClick;
}
deferral.Complete();
@@ -36,16 +36,16 @@ public class ContentDialogHandler :
async void HandleSecondaryButtonClick(FluentAvalonia.UI.Controls.ContentDialog sender,
FluentAvalonia.UI.Controls.ContentDialogButtonClickEventArgs args)
{
contentDialog.SecondaryButtonClick -= HandleSecondaryButtonClick;
if (contentDialog.DataContext is object content)
dialog.SecondaryButtonClick -= HandleSecondaryButtonClick;
if (dialog.DataContext is object content)
{
if (content is ISecondaryConfirmation secondaryConfirmation)
{
Deferral deferral = args.GetDeferral();
if (!await secondaryConfirmation.Confirm())
if (!await secondaryConfirmation.ConfirmSecondary())
{
args.Cancel = true;
contentDialog.SecondaryButtonClick += HandleSecondaryButtonClick;
dialog.SecondaryButtonClick += HandleSecondaryButtonClick;
}
deferral.Complete();
@@ -56,11 +56,11 @@ public class ContentDialogHandler :
async void HandleClosing(FluentAvalonia.UI.Controls.ContentDialog sender,
FluentAvalonia.UI.Controls.ContentDialogClosingEventArgs args)
{
if (args.Result == FluentAvalonia.UI.Controls.ContentDialogResult.Primary ||
args.Result == FluentAvalonia.UI.Controls.ContentDialogResult.Secondary)
if (args.Result is FluentAvalonia.UI.Controls.ContentDialogResult.Primary ||
args.Result is FluentAvalonia.UI.Controls.ContentDialogResult.Secondary)
{
contentDialog.Closing -= HandleClosing;
if (contentDialog.DataContext is object content)
dialog.Closing -= HandleClosing;
if (dialog.DataContext is object content)
{
bool cancelled = false;
if (content is IConfirmation confirmation)
@@ -71,7 +71,7 @@ public class ContentDialogHandler :
args.Cancel = true;
cancelled = true;
contentDialog.Closing += HandleClosing;
dialog.Closing += HandleClosing;
}
deferral.Complete();
@@ -91,8 +91,8 @@ public class ContentDialogHandler :
async void HandleOpened(FluentAvalonia.UI.Controls.ContentDialog sender,
EventArgs args)
{
contentDialog.Opened -= HandleOpened;
if (contentDialog.DataContext is object content)
dialog.Opened -= HandleOpened;
if (dialog.DataContext is object content)
{
if (content is IActivated activated)
{
@@ -104,8 +104,8 @@ public class ContentDialogHandler :
async void HandleClosed(FluentAvalonia.UI.Controls.ContentDialog sender,
FluentAvalonia.UI.Controls.ContentDialogClosedEventArgs args)
{
contentDialog.Closed -= HandleClosed;
if (contentDialog.DataContext is object content)
dialog.Closed -= HandleClosed;
if (dialog.DataContext is object content)
{
if (content is IDeactivated deactivated)
{
@@ -114,17 +114,17 @@ public class ContentDialogHandler :
}
}
contentDialog.Opened += HandleOpened;
contentDialog.Closing += HandleClosing;
contentDialog.Closed += HandleClosed;
dialog.Opened += HandleOpened;
dialog.Closing += HandleClosing;
dialog.Closed += HandleClosed;
contentDialog.PrimaryButtonClick += HandlePrimaryButtonClick;
contentDialog.SecondaryButtonClick += HandleSecondaryButtonClick;
dialog.PrimaryButtonClick += HandlePrimaryButtonClick;
dialog.SecondaryButtonClick += HandleSecondaryButtonClick;
await contentDialog.ShowAsync();
await dialog.ShowAsync();
contentDialog.PrimaryButtonClick += HandlePrimaryButtonClick;
contentDialog.SecondaryButtonClick += HandleSecondaryButtonClick;
dialog.PrimaryButtonClick += HandlePrimaryButtonClick;
dialog.SecondaryButtonClick += HandleSecondaryButtonClick;
}
}
}
@@ -35,6 +35,7 @@ public static class IServiceCollectionExtensions
services.AddHandler<ContentControlHandler>(nameof(ContentControl));
services.AddHandler<FrameHandler>(nameof(Frame));
services.AddHandler<ContentDialogHandler>(nameof(ContentDialog));
services.AddHandler<TaskDialogHandler>(nameof(TaskDialog));
services.AddScoped<INavigationRegionCollection, NavigationRegionCollection>(provider => new NavigationRegionCollection
{
@@ -67,6 +68,7 @@ public static class IServiceCollectionExtensions
services.AddHandler<ContentControlHandler>(nameof(ContentControl));
services.AddHandler<FrameHandler>(nameof(Frame));
services.AddHandler<ContentDialogHandler>(nameof(ContentDialog));
services.AddHandler<TaskDialogHandler>(nameof(TaskDialog));
})));
return services;
+61
View File
@@ -0,0 +1,61 @@
using Avalonia.Controls;
using FluentAvalonia.Core;
using Toolkit.Foundation;
using Toolkit.UI.Controls.Avalonia;
namespace Toolkit.Avalonia;
public class TaskDialogHandler(ITopLevelProvider topLevelProvider) :
INotificationHandler<NavigateEventArgs<TaskDialog>>
{
public async Task Handle(NavigateEventArgs<TaskDialog> args)
{
if (args.Template is TaskDialog dialog)
{
if (topLevelProvider.Get() is TopLevel topLevel)
{
dialog.XamlRoot = topLevel;
dialog.DataContext = args.Content;
async void HandleClosing(FluentAvalonia.UI.Controls.TaskDialog sender,
FluentAvalonia.UI.Controls.TaskDialogClosingEventArgs args)
{
dialog.Closing -= HandleClosing;
if (dialog.DataContext is object content)
{
bool cancelled = false;
if (args.Result is TaskDialogResult result)
{
if (result is TaskDialogResult.OK && content is
IPrimaryConfirmation primaryConfirmation)
{
Deferral deferral = args.GetDeferral();
if (!await primaryConfirmation.ConfirmPrimary())
{
args.Cancel = true;
cancelled = true;
dialog.Closing += HandleClosing;
}
deferral.Complete();
}
}
if (!cancelled)
{
if (content is IDeactivating deactivating)
{
await deactivating.OnDeactivating();
}
}
}
}
dialog.Closing += HandleClosing;
await dialog.ShowAsync();
}
}
}
}
+1 -1
View File
@@ -2,5 +2,5 @@
public interface ISecondaryConfirmation
{
Task<bool> Confirm();
Task<bool> ConfirmSecondary();
}
@@ -1,7 +1,15 @@
namespace Toolkit.UI.Controls.Avalonia;
using Avalonia.Controls.Chrome;
namespace Toolkit.UI.Controls.Avalonia;
public class AppWindow : FluentAvalonia.UI.Windowing.AppWindow
{
protected override Type StyleKeyOverride =>
typeof(FluentAvalonia.UI.Windowing.AppWindow);
public AppWindow()
{
TitleBar.ExtendsContentIntoTitleBar = true;
TitleBar.TitleBarHitTestType = FluentAvalonia.UI.Windowing.TitleBarHitTestType.Complex;
}
}
@@ -1,27 +0,0 @@
<ResourceDictionary
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Toolkit.UI.Controls.Avalonia">
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Light">
<StaticResource x:Key="OverflowItemBackgroundSelected" ResourceKey="SubtleFillColorTransparentBrush" />
</ResourceDictionary>
<ResourceDictionary x:Key="Dark">
<StaticResource x:Key="OverflowItemBackgroundSelected" ResourceKey="SubtleFillColorTransparentBrush" />
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
<ControlTheme x:Key="{x:Type controls:CarouselViewItem}" TargetType="controls:CarouselViewItem">
<Setter Property="Background" Value="Transparent" />
<Setter Property="Template">
<ControlTemplate>
<ContentPresenter
x:Name="Content"
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
FontFamily="{StaticResource ContentControlThemeFontFamily}"
FontSize="{StaticResource ControlContentThemeFontSize}"
Foreground="{TemplateBinding Foreground}" />
</ControlTemplate>
</Setter>
</ControlTheme>
</ResourceDictionary>
@@ -0,0 +1,33 @@
<ResourceDictionary
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Toolkit.UI.Controls.Avalonia">
<Thickness x:Key="SettingsExpanderPadding">16</Thickness>
<ControlTheme x:Key="{x:Type controls:ContentCard}" TargetType="controls:ContentCard">
<Setter Property="Background" Value="{DynamicResource ExpanderHeaderBackground}" />
<Setter Property="BorderBrush" Value="{DynamicResource ExpanderHeaderBorderBrush}" />
<Setter Property="BorderThickness" Value="{DynamicResource ExpanderHeaderBorderThickness}" />
<Setter Property="CornerRadius" Value="{DynamicResource ControlCornerRadius}" />
<Setter Property="Padding" Value="{DynamicResource SettingsExpanderPadding}" />
<Setter Property="Template">
<ControlTemplate>
<Border
Name="Root"
Padding="{TemplateBinding Padding}"
Background="{TemplateBinding Background}"
BackgroundSizing="{TemplateBinding BackgroundSizing}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{TemplateBinding CornerRadius}">
<ContentPresenter
x:Name="Content"
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
FontFamily="{StaticResource ContentControlThemeFontFamily}"
FontSize="{StaticResource ControlContentThemeFontSize}"
Foreground="{TemplateBinding Foreground}" />
</Border>
</ControlTemplate>
</Setter>
</ControlTheme>
</ResourceDictionary>
@@ -2,6 +2,6 @@
namespace Toolkit.UI.Controls.Avalonia;
public class CardContent : ContentControl
public class ContentCard : ContentControl
{
}
@@ -6,12 +6,12 @@
<ResourceDictionary x:Key="Light">
<StaticResource x:Key="ImageCropperThumbBackground" ResourceKey="AccentFillColorDefaultBrush" />
<StaticResource x:Key="ImageCropperThumbBrush" ResourceKey="ControlElevationBorderBrush" />
<StaticResource x:Key="ImageCropperThumbBackground" ResourceKey="ControlSolidFillColorDefaultBrush" />
<StaticResource x:Key="ImageCropperOuterThumbBackground" ResourceKey="ControlSolidFillColorDefaultBrush" />
</ResourceDictionary>
<ResourceDictionary x:Key="Dark">
<StaticResource x:Key="ImageCropperThumbBackground" ResourceKey="AccentFillColorDefaultBrush" />
<StaticResource x:Key="ImageCropperThumbBrush" ResourceKey="ControlElevationBorderBrush" />
<StaticResource x:Key="ImageCropperThumbBackground" ResourceKey="ControlSolidFillColorDefaultBrush" />
<StaticResource x:Key="ImageCropperOuterThumbBackground" ResourceKey="ControlSolidFillColorDefaultBrush" />
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
<CornerRadius x:Key="ImageCropperThumbCornerRadius">10</CornerRadius>
@@ -29,10 +29,10 @@
<ControlTemplate>
<Border
Margin="-2"
Background="{DynamicResource ImageCropperThumbBackground}"
Background="{DynamicResource ImageCropperOuterThumbBackground}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{DynamicResource ImageCropperThumbCornerRadius}">
CornerRadius="{DynamicResource ImageCropperOuterThumbCornerRadius}">
<Ellipse
Name="InnerThumb"
Width="{DynamicResource ImageCropperInnerThumbWidth}"
@@ -0,0 +1,8 @@
namespace Toolkit.UI.Controls.Avalonia;
public class TaskDialog :
FluentAvalonia.UI.Controls.TaskDialog
{
protected override Type StyleKeyOverride =>
typeof(FluentAvalonia.UI.Controls.TaskDialog);
}
@@ -0,0 +1,4 @@
namespace Toolkit.UI.Controls.Avalonia;
public class TaskDialogButton :
FluentAvalonia.UI.Controls.TaskDialogButton;
@@ -0,0 +1,12 @@
namespace Toolkit.UI.Controls.Avalonia;
public enum TaskDialogResult
{
None,
OK,
Cancel,
Yes,
No,
Retry,
Close
}
@@ -2,6 +2,8 @@
<Styles.Resources>
<ResourceDictionary>
<FontFamily x:Key="FluentThemeFontFamily">/Fonts/#FluentSystemIcons-Resizable</FontFamily>
<Thickness x:Key="TaskDialogHeaderPadding">60 0 12 9</Thickness>
<Thickness x:Key="TaskDialogHeaderPaddingNoIcon">18 0 12 9</Thickness>
<ControlTheme x:Key="TextBoxButtonStyle" TargetType="Button">
<Setter Property="Foreground" Value="{DynamicResource TextControlButtonForeground}" />
<Setter Property="Background" Value="Transparent" />
@@ -70,6 +72,7 @@
<MergeResourceInclude Source="../ContentBadge/ContentBadge.axaml" />
<MergeResourceInclude Source="../TabStrip/TabStrip.axaml" />
<MergeResourceInclude Source="../ImageCropper/ImageCropper.axaml" />
<MergeResourceInclude Source="../ContentCard/ContentCard.axaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Styles.Resources>