feat: add close button.
This commit is contained in:
@@ -12,6 +12,7 @@
|
|||||||
<vm:ToastDemoViewModel />
|
<vm:ToastDemoViewModel />
|
||||||
</Design.DataContext>
|
</Design.DataContext>
|
||||||
<StackPanel>
|
<StackPanel>
|
||||||
|
<ToggleSwitch IsChecked="{Binding ShowClose}" Content="ShowClose"/>
|
||||||
<StackPanel Orientation="Horizontal" Spacing="20">
|
<StackPanel Orientation="Horizontal" Spacing="20">
|
||||||
<Button Command="{Binding ShowNormal}" CommandParameter="{Binding $self.Content}" Content="Information" />
|
<Button Command="{Binding ShowNormal}" CommandParameter="{Binding $self.Content}" Content="Information" />
|
||||||
<Button Command="{Binding ShowNormal}" CommandParameter="{Binding $self.Content}" Content="Success" Classes="Success" />
|
<Button Command="{Binding ShowNormal}" CommandParameter="{Binding $self.Content}" Content="Success" Classes="Success" />
|
||||||
|
|||||||
@@ -10,6 +10,9 @@ public partial class ToastDemoViewModel : ObservableObject
|
|||||||
{
|
{
|
||||||
public WindowToastManager? ToastManager { get; set; }
|
public WindowToastManager? ToastManager { get; set; }
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
private bool _showClose = true;
|
||||||
|
|
||||||
[RelayCommand]
|
[RelayCommand]
|
||||||
public void ShowNormal(object obj)
|
public void ShowNormal(object obj)
|
||||||
{
|
{
|
||||||
@@ -18,6 +21,7 @@ public partial class ToastDemoViewModel : ObservableObject
|
|||||||
Enum.TryParse<NotificationType>(s, out var notificationType);
|
Enum.TryParse<NotificationType>(s, out var notificationType);
|
||||||
ToastManager?.Show(
|
ToastManager?.Show(
|
||||||
new Toast("This is message"),
|
new Toast("This is message"),
|
||||||
|
showClose: ShowClose,
|
||||||
type: notificationType);
|
type: notificationType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,6 +40,7 @@ public partial class ToastDemoViewModel : ObservableObject
|
|||||||
Enum.TryParse<NotificationType>(s, out var notificationType);
|
Enum.TryParse<NotificationType>(s, out var notificationType);
|
||||||
ToastManager?.Show(
|
ToastManager?.Show(
|
||||||
new Toast("This is message"),
|
new Toast("This is message"),
|
||||||
|
showClose: ShowClose,
|
||||||
type: notificationType,
|
type: notificationType,
|
||||||
classes: ["Light"]);
|
classes: ["Light"]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,17 +3,12 @@
|
|||||||
xmlns:u="https://irihi.tech/ursa">
|
xmlns:u="https://irihi.tech/ursa">
|
||||||
<Design.PreviewWith>
|
<Design.PreviewWith>
|
||||||
<ThemeVariantScope RequestedThemeVariant="Dark">
|
<ThemeVariantScope RequestedThemeVariant="Dark">
|
||||||
<StackPanel>
|
<StackPanel Orientation="Horizontal">
|
||||||
|
<u:ToastCard ShowClose="False" />
|
||||||
<u:ToastCard>
|
<u:ToastCard>
|
||||||
Hello, Semi.Avalonia!
|
Hello, Semi.Avalonia!
|
||||||
</u:ToastCard>
|
</u:ToastCard>
|
||||||
<u:ToastCard NotificationType="Success">
|
<u:ToastCard NotificationType="Success" ShowClose="False">
|
||||||
<u:Toast Content="Hello, Semi.Avalonia!" />
|
|
||||||
</u:ToastCard>
|
|
||||||
<u:ToastCard NotificationType="Warning">
|
|
||||||
<u:Toast Content="Hello, Semi.Avalonia!" />
|
|
||||||
</u:ToastCard>
|
|
||||||
<u:ToastCard NotificationType="Error">
|
|
||||||
<u:Toast Content="Hello, Semi.Avalonia!" />
|
<u:Toast Content="Hello, Semi.Avalonia!" />
|
||||||
</u:ToastCard>
|
</u:ToastCard>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
@@ -35,7 +30,6 @@
|
|||||||
|
|
||||||
<ControlTheme x:Key="{x:Type u:ToastCard}" TargetType="u:ToastCard">
|
<ControlTheme x:Key="{x:Type u:ToastCard}" TargetType="u:ToastCard">
|
||||||
<Setter Property="UseLayoutRounding" Value="True" />
|
<Setter Property="UseLayoutRounding" Value="True" />
|
||||||
<Setter Property="MinWidth" Value="{DynamicResource NotificationCardMinWidth}" />
|
|
||||||
<Setter Property="RenderTransformOrigin" Value="50%,75%" />
|
<Setter Property="RenderTransformOrigin" Value="50%,75%" />
|
||||||
<Setter Property="BorderThickness" Value="{DynamicResource NotificationCardBorderThickness}" />
|
<Setter Property="BorderThickness" Value="{DynamicResource NotificationCardBorderThickness}" />
|
||||||
<Setter Property="BorderBrush" Value="{DynamicResource NotificationCardBorderBrush}" />
|
<Setter Property="BorderBrush" Value="{DynamicResource NotificationCardBorderBrush}" />
|
||||||
@@ -53,40 +47,44 @@
|
|||||||
Padding="{DynamicResource NotificationCardPadding}"
|
Padding="{DynamicResource NotificationCardPadding}"
|
||||||
BoxShadow="{DynamicResource NotificationCardBoxShadow}"
|
BoxShadow="{DynamicResource NotificationCardBoxShadow}"
|
||||||
BorderBrush="{TemplateBinding BorderBrush}"
|
BorderBrush="{TemplateBinding BorderBrush}"
|
||||||
|
VerticalAlignment="Stretch"
|
||||||
BorderThickness="{TemplateBinding BorderThickness}"
|
BorderThickness="{TemplateBinding BorderThickness}"
|
||||||
CornerRadius="{TemplateBinding CornerRadius}">
|
CornerRadius="{TemplateBinding CornerRadius}">
|
||||||
<DockPanel>
|
<StackPanel Orientation="Horizontal">
|
||||||
<PathIcon
|
<PathIcon
|
||||||
Name="NotificationIcon"
|
Name="NotificationIcon"
|
||||||
Width="{DynamicResource NotificationCardIconWidth}"
|
Width="{DynamicResource NotificationCardIconWidth}"
|
||||||
Height="{DynamicResource NotificationCardIconHeight}"
|
Height="{DynamicResource NotificationCardIconHeight}"
|
||||||
Margin="{DynamicResource NotificationCardIconMargin}"
|
Margin="{DynamicResource NotificationCardIconMargin}"
|
||||||
VerticalAlignment="Top"
|
|
||||||
IsVisible="False"
|
IsVisible="False"
|
||||||
Data="{DynamicResource NotificationCardInformationIconPathData}" />
|
Data="{DynamicResource NotificationCardInformationIconPathData}" />
|
||||||
<ContentControl
|
<ContentControl
|
||||||
Name="PART_Content"
|
Name="PART_Content"
|
||||||
|
Margin="12 0"
|
||||||
|
VerticalContentAlignment="Center"
|
||||||
Content="{TemplateBinding Content}">
|
Content="{TemplateBinding Content}">
|
||||||
<ContentControl.DataTemplates>
|
<ContentControl.DataTemplates>
|
||||||
<DataTemplate DataType="u:IToast">
|
<DataTemplate DataType="u:IToast">
|
||||||
<SelectableTextBlock
|
<SelectableTextBlock
|
||||||
Foreground="{DynamicResource NotificationCardMessageForeground}"
|
Foreground="{DynamicResource NotificationCardTitleForeground}"
|
||||||
FontSize="{DynamicResource NotificationCardMessageFontSize}"
|
FontWeight="{DynamicResource NotificationCardTitleFontWeight}"
|
||||||
FontWeight="{DynamicResource NotificationCardMessageFontWeight}"
|
|
||||||
Text="{Binding Content}"
|
Text="{Binding Content}"
|
||||||
TextWrapping="Wrap" />
|
TextWrapping="Wrap" />
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
<DataTemplate DataType="x:String">
|
<DataTemplate DataType="x:String">
|
||||||
<SelectableTextBlock
|
<SelectableTextBlock
|
||||||
Foreground="{DynamicResource NotificationCardMessageForeground}"
|
Foreground="{DynamicResource NotificationCardTitleForeground}"
|
||||||
FontSize="{DynamicResource NotificationCardMessageFontSize}"
|
FontWeight="{DynamicResource NotificationCardTitleFontWeight}"
|
||||||
FontWeight="{DynamicResource NotificationCardMessageFontWeight}"
|
|
||||||
Text="{Binding}"
|
Text="{Binding}"
|
||||||
TextWrapping="Wrap" />
|
TextWrapping="Wrap" />
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</ContentControl.DataTemplates>
|
</ContentControl.DataTemplates>
|
||||||
</ContentControl>
|
</ContentControl>
|
||||||
</DockPanel>
|
<Button
|
||||||
|
Theme="{StaticResource ToastCloseButton}"
|
||||||
|
IsVisible="{TemplateBinding ShowClose}"
|
||||||
|
u:ToastCard.CloseOnClick="True" />
|
||||||
|
</StackPanel>
|
||||||
</Border>
|
</Border>
|
||||||
</Border>
|
</Border>
|
||||||
</LayoutTransformControl>
|
</LayoutTransformControl>
|
||||||
@@ -193,4 +191,31 @@
|
|||||||
</Style>
|
</Style>
|
||||||
</Style>
|
</Style>
|
||||||
</ControlTheme>
|
</ControlTheme>
|
||||||
|
|
||||||
|
<ControlTheme x:Key="ToastCloseButton" TargetType="Button">
|
||||||
|
<Setter Property="CornerRadius" Value="6" />
|
||||||
|
<Setter Property="Height" Value="24" />
|
||||||
|
<Setter Property="Width" Value="24" />
|
||||||
|
<Setter Property="Cursor" Value="Hand" />
|
||||||
|
<Setter Property="Template">
|
||||||
|
<ControlTemplate TargetType="Button">
|
||||||
|
<Border
|
||||||
|
Name="PART_Border"
|
||||||
|
Padding="{TemplateBinding Padding}"
|
||||||
|
Background="Transparent"
|
||||||
|
CornerRadius="{TemplateBinding CornerRadius}">
|
||||||
|
<PathIcon
|
||||||
|
Width="10"
|
||||||
|
Height="10"
|
||||||
|
Data="{DynamicResource WindowCloseIconGlyph}" />
|
||||||
|
</Border>
|
||||||
|
</ControlTemplate>
|
||||||
|
</Setter>
|
||||||
|
<Style Selector="^:pointerover /template/ Border">
|
||||||
|
<Setter Property="Background" Value="{DynamicResource ButtonDefaultPointeroverBackground}" />
|
||||||
|
</Style>
|
||||||
|
<Style Selector="^:pressed /template/ Border">
|
||||||
|
<Setter Property="Background" Value="{DynamicResource ButtonDefaultPressedBackground}" />
|
||||||
|
</Style>
|
||||||
|
</ControlTheme>
|
||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
||||||
@@ -20,6 +20,11 @@ public interface IToast
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
NotificationType Type { get; }
|
NotificationType Type { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a value indicating whether the toast should show a close button.
|
||||||
|
/// </summary>
|
||||||
|
bool ShowClose { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the expiration time of the toast after which it will automatically close.
|
/// Gets the expiration time of the toast after which it will automatically close.
|
||||||
/// If the value is <see cref="TimeSpan.Zero"/> then the toast will remain open until the user closes it.
|
/// If the value is <see cref="TimeSpan.Zero"/> then the toast will remain open until the user closes it.
|
||||||
|
|||||||
@@ -22,12 +22,14 @@ public class Toast : IToast, INotifyPropertyChanged
|
|||||||
/// <param name="type">The <see cref="NotificationType"/> of the toast.</param>
|
/// <param name="type">The <see cref="NotificationType"/> of the toast.</param>
|
||||||
/// <param name="expiration">The expiry time at which the toast will close.
|
/// <param name="expiration">The expiry time at which the toast will close.
|
||||||
/// Use <see cref="TimeSpan.Zero"/> for toasts that will remain open.</param>
|
/// Use <see cref="TimeSpan.Zero"/> for toasts that will remain open.</param>
|
||||||
|
/// <param name="showClose">A value indicating whether the toast should show a close button.</param>
|
||||||
/// <param name="onClick">An Action to call when the toast is clicked.</param>
|
/// <param name="onClick">An Action to call when the toast is clicked.</param>
|
||||||
/// <param name="onClose">An Action to call when the toast is closed.</param>
|
/// <param name="onClose">An Action to call when the toast is closed.</param>
|
||||||
public Toast(
|
public Toast(
|
||||||
string? content,
|
string? content,
|
||||||
NotificationType type = NotificationType.Information,
|
NotificationType type = NotificationType.Information,
|
||||||
TimeSpan? expiration = null,
|
TimeSpan? expiration = null,
|
||||||
|
bool showClose = true,
|
||||||
Action? onClick = null,
|
Action? onClick = null,
|
||||||
Action? onClose = null)
|
Action? onClose = null)
|
||||||
{
|
{
|
||||||
@@ -62,6 +64,9 @@ public class Toast : IToast, INotifyPropertyChanged
|
|||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public NotificationType Type { get; set; }
|
public NotificationType Type { get; set; }
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public bool ShowClose { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public TimeSpan Expiration { get; set; }
|
public TimeSpan Expiration { get; set; }
|
||||||
|
|
||||||
|
|||||||
@@ -77,6 +77,14 @@ public class ToastCard : ContentControl
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static readonly StyledProperty<NotificationType> NotificationTypeProperty =
|
public static readonly StyledProperty<NotificationType> NotificationTypeProperty =
|
||||||
AvaloniaProperty.Register<ToastCard, NotificationType>(nameof(NotificationType));
|
AvaloniaProperty.Register<ToastCard, NotificationType>(nameof(NotificationType));
|
||||||
|
public bool ShowClose
|
||||||
|
{
|
||||||
|
get => GetValue(ShowCloseProperty);
|
||||||
|
set => SetValue(ShowCloseProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static readonly StyledProperty<bool> ShowCloseProperty =
|
||||||
|
AvaloniaProperty.Register<ToastCard, bool>(nameof(ShowClose), true);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Defines the <see cref="ToastClosed"/> event.
|
/// Defines the <see cref="ToastClosed"/> event.
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ public class WindowToastManager : TemplatedControl, IManagedToastManager
|
|||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void Show(IToast content)
|
public void Show(IToast content)
|
||||||
{
|
{
|
||||||
Show(content, content.Type, content.Expiration, content.OnClick, content.OnClose);
|
Show(content, content.Type, content.Expiration, content.ShowClose, content.OnClick, content.OnClose);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
@@ -78,7 +78,7 @@ public class WindowToastManager : TemplatedControl, IManagedToastManager
|
|||||||
{
|
{
|
||||||
if (content is IToast toast)
|
if (content is IToast toast)
|
||||||
{
|
{
|
||||||
Show(toast, toast.Type, toast.Expiration, toast.OnClick, toast.OnClose);
|
Show(toast, toast.Type, toast.Expiration, toast.ShowClose, toast.OnClick, toast.OnClose);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -92,12 +92,14 @@ public class WindowToastManager : TemplatedControl, IManagedToastManager
|
|||||||
/// <param name="content">the content of the toast</param>
|
/// <param name="content">the content of the toast</param>
|
||||||
/// <param name="type">the type of the toast</param>
|
/// <param name="type">the type of the toast</param>
|
||||||
/// <param name="expiration">the expiration time of the toast after which it will automatically close. If the value is Zero then the toast will remain open until the user closes it</param>
|
/// <param name="expiration">the expiration time of the toast after which it will automatically close. If the value is Zero then the toast will remain open until the user closes it</param>
|
||||||
|
/// <param name="showClose">whether to show the close button</param>
|
||||||
/// <param name="onClick">an Action to be run when the toast is clicked</param>
|
/// <param name="onClick">an Action to be run when the toast is clicked</param>
|
||||||
/// <param name="onClose">an Action to be run when the toast is closed</param>
|
/// <param name="onClose">an Action to be run when the toast is closed</param>
|
||||||
/// <param name="classes">style classes to apply</param>
|
/// <param name="classes">style classes to apply</param>
|
||||||
public async void Show(object content,
|
public async void Show(object content,
|
||||||
NotificationType type,
|
NotificationType type,
|
||||||
TimeSpan? expiration = null,
|
TimeSpan? expiration = null,
|
||||||
|
bool showClose = true,
|
||||||
Action? onClick = null,
|
Action? onClick = null,
|
||||||
Action? onClose = null,
|
Action? onClose = null,
|
||||||
string[]? classes = null)
|
string[]? classes = null)
|
||||||
@@ -107,11 +109,12 @@ public class WindowToastManager : TemplatedControl, IManagedToastManager
|
|||||||
var toastControl = new ToastCard
|
var toastControl = new ToastCard
|
||||||
{
|
{
|
||||||
Content = content,
|
Content = content,
|
||||||
NotificationType = type
|
NotificationType = type,
|
||||||
|
ShowClose = showClose
|
||||||
};
|
};
|
||||||
|
|
||||||
// Add style classes if any
|
// Add style classes if any
|
||||||
if (classes != null)
|
if (classes is not null)
|
||||||
{
|
{
|
||||||
foreach (var @class in classes)
|
foreach (var @class in classes)
|
||||||
{
|
{
|
||||||
@@ -119,19 +122,14 @@ public class WindowToastManager : TemplatedControl, IManagedToastManager
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
toastControl.ToastClosed += (sender, args) =>
|
toastControl.ToastClosed += (sender, _) =>
|
||||||
{
|
{
|
||||||
onClose?.Invoke();
|
onClose?.Invoke();
|
||||||
|
|
||||||
_items?.Remove(sender);
|
_items?.Remove(sender);
|
||||||
};
|
};
|
||||||
|
|
||||||
toastControl.PointerPressed += (sender, args) =>
|
toastControl.PointerPressed += (_, _) => { onClick?.Invoke(); };
|
||||||
{
|
|
||||||
onClick?.Invoke();
|
|
||||||
|
|
||||||
(sender as ToastCard)?.Close();
|
|
||||||
};
|
|
||||||
|
|
||||||
Dispatcher.UIThread.Post(() =>
|
Dispatcher.UIThread.Post(() =>
|
||||||
{
|
{
|
||||||
@@ -153,11 +151,6 @@ public class WindowToastManager : TemplatedControl, IManagedToastManager
|
|||||||
toastControl.Close();
|
toastControl.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
|
|
||||||
{
|
|
||||||
base.OnPropertyChanged(change);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Installs the <see cref="WindowToastManager"/> within the <see cref="AdornerLayer"/>
|
/// Installs the <see cref="WindowToastManager"/> within the <see cref="AdornerLayer"/>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
Reference in New Issue
Block a user