feat: add LargeMessageBoxControl and improve MessageBox functionality
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
<ResourceDictionary
|
||||
<ResourceDictionary
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<Design.PreviewWith>
|
||||
@@ -56,4 +56,40 @@
|
||||
</Style>
|
||||
</ControlTheme>
|
||||
|
||||
<ControlTheme
|
||||
x:Key="MessageCloseButton"
|
||||
BasedOn="{StaticResource OverlayCloseButton}"
|
||||
TargetType="Button">
|
||||
<Setter Property="CornerRadius" Value="6" />
|
||||
<Setter Property="Padding" Value="4" />
|
||||
<Style Selector="^:pointerover /template/ Border">
|
||||
<Setter Property="Background" Value="{DynamicResource CaptionButtonClosePointeroverBackground}" />
|
||||
</Style>
|
||||
<Style Selector="^:pointerover /template/ PathIcon">
|
||||
<Setter Property="Foreground" Value="White" />
|
||||
</Style>
|
||||
<Style Selector="^:pressed /template/ Border">
|
||||
<Setter Property="Background" Value="{DynamicResource CaptionButtonClosePressedBackground}" />
|
||||
</Style>
|
||||
<Style Selector="^:pressed /template/ PathIcon">
|
||||
<Setter Property="Foreground" Value="White" />
|
||||
</Style>
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border
|
||||
Padding="{TemplateBinding Padding}"
|
||||
Background="Transparent"
|
||||
CornerRadius="{TemplateBinding CornerRadius}">
|
||||
<Viewbox>
|
||||
<PathIcon
|
||||
Foreground="{DynamicResource SemiColorText1}"
|
||||
Theme="{StaticResource InnerPathIcon}"
|
||||
Data="{DynamicResource SemiIconClose}" />
|
||||
</Viewbox>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
</ControlTheme>
|
||||
|
||||
|
||||
</ResourceDictionary>
|
||||
@@ -1,11 +1,11 @@
|
||||
<ResourceDictionary
|
||||
<ResourceDictionary
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:u="https://irihi.tech/ursa"
|
||||
xmlns:iri="https://irihi.tech/shared">
|
||||
<Design.PreviewWith>
|
||||
<StackPanel Margin="20">
|
||||
<u:MessageBoxControl
|
||||
<!--<u:MessageBoxControl
|
||||
Content="此修改将不可逆"
|
||||
MessageIcon="None"
|
||||
Buttons="OK" />
|
||||
@@ -21,11 +21,12 @@
|
||||
Title="确定是否要保存此修改?"
|
||||
Content="此修改将不可逆"
|
||||
MessageIcon="Warning"
|
||||
Buttons="OKCancel" />
|
||||
Buttons="OKCancel" />-->
|
||||
<u:MessageBoxControl
|
||||
Title="确定是否要保存此修改?"
|
||||
Content="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
|
||||
MessageIcon="Warning"
|
||||
Theme="{StaticResource LargeMessageBoxControl}"
|
||||
Buttons="OKCancel" />
|
||||
</StackPanel>
|
||||
</Design.PreviewWith>
|
||||
@@ -340,4 +341,170 @@
|
||||
<Setter Property="Data" Value="{DynamicResource DialogSuccessIconGlyph}" />
|
||||
</Style>
|
||||
</ControlTheme>
|
||||
|
||||
<ControlTheme x:Key="LargeMessageBoxControl" TargetType="u:MessageBoxControl">
|
||||
<Setter Property="CornerRadius" Value="6" />
|
||||
<Setter Property="Padding" Value="48 24" />
|
||||
<Setter Property="u:DialogControlBase.CanDragMove" Value="True" />
|
||||
<Setter Property="FontSize" Value="18"/>
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate TargetType="u:MessageBoxControl">
|
||||
<Border
|
||||
Padding="0"
|
||||
Focusable="True"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Classes="Shadow"
|
||||
ClipToBounds="False"
|
||||
Background="{DynamicResource SemiColorBackground3}"
|
||||
CornerRadius="{TemplateBinding CornerRadius}"
|
||||
IsHitTestVisible="True"
|
||||
Theme="{DynamicResource CardBorder}">
|
||||
<Border ClipToBounds="True" CornerRadius="{TemplateBinding CornerRadius}">
|
||||
<Grid RowDefinitions="Auto, *, Auto">
|
||||
<Grid Grid.Row="0" ColumnDefinitions="Auto, *, Auto">
|
||||
<Panel
|
||||
Name="{x:Static u:DialogControlBase.PART_TitleArea}"
|
||||
Grid.Column="0"
|
||||
Grid.ColumnSpan="3"
|
||||
Background="Transparent" />
|
||||
<PathIcon
|
||||
Name="PART_Icon"
|
||||
Grid.Column="0"
|
||||
Theme="{StaticResource InnerPathIcon}"
|
||||
Classes="ExtraLarge"
|
||||
Margin="24,24,8,0"
|
||||
VerticalAlignment="Center"
|
||||
IsHitTestVisible="False" />
|
||||
<TextBlock
|
||||
Name="PART_Title"
|
||||
Grid.Column="1"
|
||||
Margin="0,24,0,0"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="18"
|
||||
FontWeight="{DynamicResource TextBlockTitleFontWeight}"
|
||||
IsHitTestVisible="False"
|
||||
Text="{TemplateBinding Title}"
|
||||
TextTrimming="CharacterEllipsis"
|
||||
TextWrapping="NoWrap" />
|
||||
<Button
|
||||
Name="{x:Static u:MessageBoxWindow.PART_CloseButton}"
|
||||
Grid.Column="2" Height="36" Width="36"
|
||||
Margin="0,24,24,0"
|
||||
Theme="{DynamicResource MessageCloseButton}" />
|
||||
</Grid>
|
||||
<Grid
|
||||
Grid.Row="1"
|
||||
MaxWidth="{DynamicResource MessageBoxWindowContentMaxWidth}"
|
||||
Margin="{TemplateBinding Padding}">
|
||||
<ScrollViewer
|
||||
MaxHeight="300"
|
||||
HorizontalScrollBarVisibility="Disabled"
|
||||
VerticalScrollBarVisibility="Auto">
|
||||
<ContentPresenter
|
||||
Name="PART_ContentPresenter"
|
||||
VerticalAlignment="Center"
|
||||
Content="{TemplateBinding Content}"
|
||||
ContentTemplate="{TemplateBinding ContentTemplate}"
|
||||
TextAlignment="Left"
|
||||
TextWrapping="Wrap" />
|
||||
</ScrollViewer>
|
||||
</Grid>
|
||||
<StackPanel
|
||||
Grid.Row="2"
|
||||
Margin="24,0,24,24"
|
||||
Spacing="8"
|
||||
HorizontalAlignment="Right"
|
||||
Orientation="Horizontal">
|
||||
<Button Name="{x:Static u:MessageBoxControl.PART_CancelButton}" />
|
||||
<Button Name="{x:Static u:MessageBoxControl.PART_NoButton}" />
|
||||
<Button Name="{x:Static u:MessageBoxControl.PART_YesButton}" />
|
||||
<Button Name="{x:Static u:MessageBoxControl.PART_OKButton}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
<Style Selector="^ /template/ Panel#PART_TitleArea">
|
||||
<Setter Property="ContextFlyout">
|
||||
<MenuFlyout>
|
||||
<MenuItem Command="{Binding $parent[u:MessageBoxControl].Close}" Header="{DynamicResource STRING_MENU_DIALOG_CLOSE}">
|
||||
<MenuItem.Icon>
|
||||
<PathIcon
|
||||
Theme="{StaticResource InnerPathIcon}"
|
||||
Data="{DynamicResource SemiIconClose}" />
|
||||
</MenuItem.Icon>
|
||||
</MenuItem>
|
||||
</MenuFlyout>
|
||||
</Setter>
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Button#PART_CancelButton">
|
||||
<Setter Property="Grid.Column" Value="0" />
|
||||
<Setter Property="iri:ClassHelper.Classes" Value="Tertiary" />
|
||||
<Setter Property="Content" Value="{DynamicResource STRING_MENU_DIALOG_CANCEL}" />
|
||||
<Setter Property="Padding" Value="14 6"/>
|
||||
<Setter Property="FontSize" Value="18"/>
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Button#PART_NoButton">
|
||||
<Setter Property="Grid.Column" Value="1" />
|
||||
<Setter Property="iri:ClassHelper.Classes" Value="Danger" />
|
||||
<Setter Property="Content" Value="{DynamicResource STRING_MENU_DIALOG_NO}" />
|
||||
<Setter Property="Theme" Value="{DynamicResource SolidButton}" />
|
||||
<Setter Property="Padding" Value="14 6"/>
|
||||
<Setter Property="FontSize" Value="18"/>
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Button#PART_YesButton">
|
||||
<Setter Property="Grid.Column" Value="2" />
|
||||
<Setter Property="iri:ClassHelper.Classes" Value="Primary" />
|
||||
<Setter Property="Content" Value="{DynamicResource STRING_MENU_DIALOG_YES}" />
|
||||
<Setter Property="Theme" Value="{DynamicResource SolidButton}" />
|
||||
<Setter Property="Padding" Value="14 6"/>
|
||||
<Setter Property="FontSize" Value="18"/>
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Button#PART_OKButton">
|
||||
<Setter Property="Grid.Column" Value="3" />
|
||||
<Setter Property="iri:ClassHelper.Classes" Value="Primary" />
|
||||
<Setter Property="Content" Value="{DynamicResource STRING_MENU_DIALOG_OK}" />
|
||||
<Setter Property="Theme" Value="{DynamicResource SolidButton}" />
|
||||
<Setter Property="Padding" Value="14 6"/>
|
||||
<Setter Property="FontSize" Value="18"/>
|
||||
</Style>
|
||||
<Style Selector="^[MessageIcon=None] /template/ PathIcon#PART_Icon">
|
||||
<Setter Property="IsVisible" Value="False" />
|
||||
</Style>
|
||||
<Style Selector="^[MessageIcon=None] /template/ TextBlock#PART_Title">
|
||||
<Setter Property="Margin" Value="24 24 0 0" />
|
||||
</Style>
|
||||
<Style Selector="^[MessageIcon=Asterisk] /template/ PathIcon#PART_Icon, ^[MessageIcon=Information] /template/ PathIcon#PART_Icon">
|
||||
<Setter Property="IsVisible" Value="True" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource SemiBlue6}" />
|
||||
<Setter Property="Data" Value="{DynamicResource DialogInformationIconGlyph}" />
|
||||
</Style>
|
||||
<Style Selector="^[MessageIcon=Error] /template/ PathIcon#PART_Icon, ^[MessageIcon=Hand] /template/ PathIcon#PART_Icon, ^[MessageIcon=Stop] /template/ PathIcon#PART_Icon">
|
||||
<Setter Property="IsVisible" Value="True" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource SemiRed6}" />
|
||||
<Setter Property="Data" Value="{DynamicResource DialogErrorIconGlyph}" />
|
||||
</Style>
|
||||
<Style Selector="^[MessageIcon=Exclamation] /template/ PathIcon#PART_Icon">
|
||||
<Setter Property="IsVisible" Value="True" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource SemiYellow6}" />
|
||||
<Setter Property="Data" Value="{DynamicResource DialogWarningIconGlyph}" />
|
||||
</Style>
|
||||
<Style Selector="^[MessageIcon=Question] /template/ PathIcon#PART_Icon">
|
||||
<Setter Property="IsVisible" Value="True" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource SemiBlue6}" />
|
||||
<Setter Property="Data" Value="{DynamicResource DialogQuestionIconGlyph}" />
|
||||
</Style>
|
||||
<Style Selector="^[MessageIcon=Warning] /template/ PathIcon#PART_Icon">
|
||||
<Setter Property="IsVisible" Value="True" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource SemiOrange6}" />
|
||||
<Setter Property="Data" Value="{DynamicResource DialogWarningIconGlyph}" />
|
||||
</Style>
|
||||
<Style Selector="^[MessageIcon=Success] /template/ PathIcon#PART_Icon">
|
||||
<Setter Property="IsVisible" Value="True" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource SemiGreen6}" />
|
||||
<Setter Property="Data" Value="{DynamicResource DialogSuccessIconGlyph}" />
|
||||
</Style>
|
||||
</ControlTheme>
|
||||
</ResourceDictionary>
|
||||
@@ -133,15 +133,22 @@ public class Marquee : ContentControl
|
||||
|
||||
private void TimerOnTick(object? sender, System.EventArgs e)
|
||||
{
|
||||
if (Presenter is null) return;
|
||||
var layoutValues = Dispatcher.UIThread.Invoke(GetLayoutValues);
|
||||
var location = UpdateLocation(layoutValues);
|
||||
if (location is null) return;
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
try
|
||||
{
|
||||
Canvas.SetTop(Presenter, location.Value.top);
|
||||
Canvas.SetLeft(Presenter, location.Value.left);
|
||||
}, DispatcherPriority.Render);
|
||||
if (Presenter is null) return;
|
||||
var layoutValues = Dispatcher.UIThread.Invoke(GetLayoutValues);
|
||||
var location = UpdateLocation(layoutValues);
|
||||
if (location is null) return;
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
Canvas.SetTop(Presenter, location.Value.top);
|
||||
Canvas.SetLeft(Presenter, location.Value.left);
|
||||
}, DispatcherPriority.Render);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
// pass
|
||||
}
|
||||
}
|
||||
|
||||
private void InvalidatePresenterPosition()
|
||||
|
||||
@@ -2,6 +2,8 @@ using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.ApplicationLifetimes;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Styling;
|
||||
using Ursa.Common;
|
||||
|
||||
namespace Ursa.Controls;
|
||||
@@ -81,6 +83,7 @@ public static class MessageBox
|
||||
MessageIcon = icon,
|
||||
[KeyboardNavigation.TabNavigationProperty] = KeyboardNavigationMode.Cycle
|
||||
};
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(styleClass))
|
||||
{
|
||||
var styles = styleClass!.Split(Constants.SpaceSeparator, StringSplitOptions.RemoveEmptyEntries);
|
||||
@@ -90,4 +93,92 @@ public static class MessageBox
|
||||
var result = await messageControl.ShowAsync<MessageBoxResult>();
|
||||
return result;
|
||||
}
|
||||
|
||||
public static async Task<MessageBoxResult> ShowLargeOverlayAsync(
|
||||
string message,
|
||||
string? title = null,
|
||||
MessageBoxIcon icon = MessageBoxIcon.None,
|
||||
MessageBoxButton button = MessageBoxButton.OK,
|
||||
string yesString = "",
|
||||
string noString = "",
|
||||
string cancelString = "",
|
||||
string okString = "")
|
||||
{
|
||||
var host = OverlayDialogManager.GetHost(null, null);
|
||||
if (host is null) return MessageBoxResult.None;
|
||||
var messageControl = new MessageBoxControl
|
||||
{
|
||||
Content = message,
|
||||
Title = title,
|
||||
Buttons = button,
|
||||
MessageIcon = icon,
|
||||
[KeyboardNavigation.TabNavigationProperty] = KeyboardNavigationMode.Cycle
|
||||
};
|
||||
if (Application.Current?.TryGetResource("LargeMessageBoxControl", ThemeVariant.Default, out var themeObj) == true
|
||||
&& themeObj is ControlTheme theme)
|
||||
{
|
||||
messageControl.Theme = theme;
|
||||
}
|
||||
|
||||
object? originalYes = null;
|
||||
object? originalNo = null;
|
||||
object? originalCancel = null;
|
||||
object? originalOk = null;
|
||||
var hadYes = false;
|
||||
var hadNo = false;
|
||||
var hadCancel = false;
|
||||
var hadOk = false;
|
||||
if (!string.IsNullOrEmpty(yesString))
|
||||
{
|
||||
hadYes = messageControl.Resources.TryGetValue("STRING_MENU_DIALOG_YES", out originalYes);
|
||||
messageControl.Resources["STRING_MENU_DIALOG_YES"] = yesString;
|
||||
}
|
||||
if (!string.IsNullOrEmpty(noString))
|
||||
{
|
||||
hadNo = messageControl.Resources.TryGetValue("STRING_MENU_DIALOG_NO", out originalNo);
|
||||
messageControl.Resources["STRING_MENU_DIALOG_NO"] = noString;
|
||||
}
|
||||
if (!string.IsNullOrEmpty(cancelString))
|
||||
{
|
||||
hadCancel = messageControl.Resources.TryGetValue("STRING_MENU_DIALOG_CANCEL", out originalCancel);
|
||||
messageControl.Resources["STRING_MENU_DIALOG_CANCEL"] = cancelString;
|
||||
}
|
||||
if (!string.IsNullOrEmpty(okString))
|
||||
{
|
||||
hadOk = messageControl.Resources.TryGetValue("STRING_MENU_DIALOG_OK", out originalOk);
|
||||
messageControl.Resources["STRING_MENU_DIALOG_OK"] = okString;
|
||||
}
|
||||
|
||||
DialogControlBase.SetCanDragMove(messageControl, false);
|
||||
|
||||
host.AddModalDialog(messageControl);
|
||||
try
|
||||
{
|
||||
var result = await messageControl.ShowAsync<MessageBoxResult>();
|
||||
return result;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (!string.IsNullOrEmpty(yesString))
|
||||
{
|
||||
if (hadYes) messageControl.Resources["STRING_MENU_DIALOG_YES"] = originalYes!;
|
||||
else messageControl.Resources.Remove("STRING_MENU_DIALOG_YES");
|
||||
}
|
||||
if (!string.IsNullOrEmpty(noString))
|
||||
{
|
||||
if (hadNo) messageControl.Resources["STRING_MENU_DIALOG_NO"] = originalNo!;
|
||||
else messageControl.Resources.Remove("STRING_MENU_DIALOG_NO");
|
||||
}
|
||||
if (!string.IsNullOrEmpty(cancelString))
|
||||
{
|
||||
if (hadCancel) messageControl.Resources["STRING_MENU_DIALOG_CANCEL"] = originalCancel!;
|
||||
else messageControl.Resources.Remove("STRING_MENU_DIALOG_CANCEL");
|
||||
}
|
||||
if (!string.IsNullOrEmpty(okString))
|
||||
{
|
||||
if (hadOk) messageControl.Resources["STRING_MENU_DIALOG_OK"] = originalOk!;
|
||||
else messageControl.Resources.Remove("STRING_MENU_DIALOG_OK");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -104,8 +104,8 @@ public class MessageBoxControl : DialogControlBase
|
||||
|
||||
private void SetButtonVisibility()
|
||||
{
|
||||
var closeButtonVisible = Buttons != MessageBoxButton.YesNo;
|
||||
IsVisibleProperty.SetValue(closeButtonVisible, _closeButton);
|
||||
//var closeButtonVisible = Buttons != MessageBoxButton.YesNo;
|
||||
IsVisibleProperty.SetValue(true, _closeButton);
|
||||
switch (Buttons)
|
||||
{
|
||||
case MessageBoxButton.OK:
|
||||
@@ -137,7 +137,7 @@ public class MessageBoxControl : DialogControlBase
|
||||
{
|
||||
MessageBoxButton.OK => MessageBoxResult.OK,
|
||||
MessageBoxButton.OKCancel => MessageBoxResult.Cancel,
|
||||
MessageBoxButton.YesNo => MessageBoxResult.No,
|
||||
MessageBoxButton.YesNo => MessageBoxResult.Cancel,
|
||||
MessageBoxButton.YesNoCancel => MessageBoxResult.Cancel,
|
||||
_ => MessageBoxResult.None
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user