Merge pull request #71 from irihitech/dialog

Dialog System, and MessageBox remake
This commit is contained in:
Dong Bin
2024-01-27 23:03:49 +08:00
committed by GitHub
46 changed files with 2562 additions and 174 deletions

View File

@@ -0,0 +1,20 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Ursa.Demo.Dialogs"
x:DataType="local:DialogWithActionViewModel"
x:CompileBindings="True"
Background="{DynamicResource SemiYellow1}"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Ursa.Demo.Dialogs.DialogWithAction">
<StackPanel Margin="24">
<TextBlock FontSize="16" FontWeight="600" Margin="8" Text="{Binding Title}"></TextBlock>
<Calendar SelectedDate="{Binding Date}" ></Calendar>
<StackPanel HorizontalAlignment="Right" Orientation="Horizontal" Spacing="8">
<Button Content="Dialog" Command="{Binding DialogCommand}"></Button>
<Button Content="OK" Command="{Binding OKCommand}"></Button>
<Button Content="Cancel" Command="{Binding CancelCommand}"></Button>
</StackPanel>
</StackPanel>
</UserControl>

View File

@@ -0,0 +1,13 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
namespace Ursa.Demo.Dialogs;
public partial class DialogWithAction : UserControl
{
public DialogWithAction()
{
InitializeComponent();
}
}

View File

@@ -0,0 +1,50 @@
using System;
using System.Threading.Tasks;
using System.Windows.Input;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Ursa.Controls;
namespace Ursa.Demo.Dialogs;
public partial class DialogWithActionViewModel: ObservableObject, IDialogContext
{
[ObservableProperty] private string _title;
[ObservableProperty] private DateTime _date;
public void Close()
{
Closed?.Invoke(this, false);
}
public event EventHandler<object?>? Closed;
public ICommand OKCommand { get; set; }
public ICommand CancelCommand { get; set; }
public ICommand DialogCommand { get; set; }
public DialogWithActionViewModel()
{
OKCommand = new RelayCommand(OK);
CancelCommand = new RelayCommand(Cancel);
DialogCommand = new AsyncRelayCommand(ShowDialog);
Title = "Please select a date";
Date = DateTime.Now;
}
private void OK()
{
Closed?.Invoke(this, true);
}
private void Cancel()
{
Closed?.Invoke(this, false);
}
private async Task ShowDialog()
{
await OverlayDialog.ShowCustomModalAsync<DialogWithAction, DialogWithActionViewModel, bool>(new DialogWithActionViewModel());
}
}

View File

@@ -0,0 +1,13 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
xmlns:local="clr-namespace:Ursa.Demo.Dialogs"
x:DataType="local:PlainDialogViewModel"
x:CompileBindings="True"
x:Class="Ursa.Demo.Dialogs.PlainDialog">
<StackPanel>
<Calendar SelectedDate="{Binding Date}" ></Calendar>
</StackPanel>
</UserControl>

View File

@@ -0,0 +1,13 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
namespace Ursa.Demo.Dialogs;
public partial class PlainDialog : UserControl
{
public PlainDialog()
{
InitializeComponent();
}
}

View File

@@ -0,0 +1,15 @@
using System;
using CommunityToolkit.Mvvm.ComponentModel;
namespace Ursa.Demo.Dialogs;
public class PlainDialogViewModel: ObservableObject
{
private DateTime? _date;
public DateTime? Date
{
get => _date;
set => SetProperty(ref _date, value);
}
}

View File

@@ -6,6 +6,7 @@ public static class MenuKeys
public const string MenuKeyBadge = "Badge";
public const string MenuKeyBanner = "Banner";
public const string MenuKeyButtonGroup = "ButtonGroup";
public const string MenuKeyDialog = "Dialog";
public const string MenuKeyDivider = "Divider";
public const string MenuKeyDualBadge = "DualBadge";
public const string MenuKeyEnumSelector = "EnumSelector";

View File

@@ -0,0 +1,78 @@
<UserControl
x:Class="Ursa.Demo.Pages.DialogDemo"
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:u="https://irihi.tech/ursa"
xmlns:vm="using:Ursa.Demo.ViewModels"
d:DesignHeight="450"
d:DesignWidth="800"
x:CompileBindings="True"
x:DataType="vm:DialogDemoViewModel"
mc:Ignorable="d">
<Grid ColumnDefinitions="Auto, *">
<TabControl Grid.Column="0" Width="300">
<TabItem Header="Default">
<StackPanel>
<ToggleSwitch
Name="overlay"
Content="Window/Overlay"
IsChecked="{Binding IsWindow}"
OffContent="Overlay"
OnContent="Window" />
<ToggleSwitch
Content="Global/Local"
IsVisible="{Binding !#overlay.IsChecked}"
IsChecked="{Binding IsGlobal}"
OffContent="Local"
OnContent="Global" />
<ToggleSwitch
Content="Modal/Regular"
IsVisible="{Binding !#overlay.IsChecked}"
IsChecked="{Binding IsModal}"
OffContent="Regular"
OnContent="Modal" />
<StackPanel Orientation="Horizontal">
<TextBlock Text="Buttons" />
<ComboBox ItemsSource="{Binding Buttons}" SelectedItem="{Binding SelectedButton}" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Mode" />
<ComboBox ItemsSource="{Binding Modes}" SelectedItem="{Binding SelectedMode}"/>
</StackPanel>
<Button Content="Show Dialog" Command="{Binding ShowDialogCommand}" />
<TextBlock>
<Run Text="Default Result: "></Run>
<Run Text="{Binding DefaultResult}"/>
</TextBlock>
<TextBlock>
<Run Text="Dialog Date: "></Run>
<Run Text="{Binding Date}"/>
</TextBlock>
</StackPanel>
</TabItem>
<TabItem Header="Custom">
<StackPanel>
<ToggleSwitch Content="Window/Overlay" OffContent="Overlay" OnContent="Window" IsChecked="{Binding IsWindow}" Name="overlay2" />
<ToggleSwitch Content="Global/Local" IsVisible="{Binding !#overlay2.IsChecked}" OffContent="Local" OnContent="Global" IsChecked="{Binding IsGlobal}" />
<ToggleSwitch Content="Modal/Regular" IsVisible="{Binding !#overlay2.IsChecked}" OffContent="Regular" OnContent="Modal" IsChecked="{Binding IsModal}" />
<Button Content="Show Dialog" Command="{Binding ShowCustomDialogCommand}" />
<TextBlock>
<Run Text="Custom Result: "></Run>
<Run Text="{Binding Result}"/>
</TextBlock>
<TextBlock>
<Run Text="Dialog Date: "></Run>
<Run Text="{Binding Date}"/>
</TextBlock>
</StackPanel>
</TabItem>
</TabControl>
<Grid Grid.Column="1">
<Border ClipToBounds="True" CornerRadius="20" BorderThickness="1" BorderBrush="{DynamicResource SemiGrey1}">
<u:OverlayDialogHost HostId="LocalHost" />
</Border>
</Grid>
</Grid>
</UserControl>

View File

@@ -0,0 +1,13 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
namespace Ursa.Demo.Pages;
public partial class DialogDemo : UserControl
{
public DialogDemo()
{
InitializeComponent();
}
}

View File

@@ -20,6 +20,7 @@
<ComboBox ItemsSource="{Binding Icons}" SelectedItem="{Binding SelectedIcon}" />
<ToggleSwitch Content="Try Long Message" IsChecked="{Binding UseLong}"></ToggleSwitch>
<ToggleSwitch Content="Show Title" IsChecked="{Binding UseTitle}"></ToggleSwitch>
<ToggleSwitch Content="Overlay" IsChecked="{Binding UseOverlay}"></ToggleSwitch>
<Button Command="{Binding DefaultMessageBoxCommand}" Content="Default" />
<Button Command="{Binding OkCommand}" Content="OK" />
<Button Command="{Binding OkCancelCommand}" Content="OKCancel" />

View File

@@ -0,0 +1,152 @@
using System;
using System.Collections.ObjectModel;
using System.Threading.Tasks;
using System.Windows.Input;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Ursa.Common;
using Ursa.Controls;
using Ursa.Demo.Dialogs;
using Ursa.Demo.Pages;
namespace Ursa.Demo.ViewModels;
public class DialogDemoViewModel: ObservableObject
{
public ICommand ShowDialogCommand { get; set; }
public ICommand ShowCustomDialogCommand { get; set; }
private DialogMode _selectedMode;
public DialogMode SelectedMode
{
get => _selectedMode;
set => SetProperty(ref _selectedMode, value);
}
public ObservableCollection<DialogMode> Modes { get; set; }
private DialogButton _selectedButton;
public DialogButton SelectedButton
{
get => _selectedButton;
set => SetProperty(ref _selectedButton, value);
}
public ObservableCollection<DialogButton> Buttons { get; set; }
private bool _isWindow;
public bool IsWindow
{
get => _isWindow;
set => SetProperty(ref _isWindow, value);
}
private bool _isGlobal;
public bool IsGlobal
{
get => _isGlobal;
set => SetProperty(ref _isGlobal, value);
}
private bool _isModal;
public bool IsModal
{
get => _isModal;
set => SetProperty(ref _isModal, value);
}
private DialogResult? _defaultResult;
public DialogResult? DefaultResult
{
get => _defaultResult;
set => SetProperty(ref _defaultResult, value);
}
private bool _result;
public bool Result
{
get => _result;
set => SetProperty(ref _result, value);
}
private DateTime? _date;
public DateTime? Date
{
get => _date;
set => SetProperty(ref _date, value);
}
public DialogDemoViewModel()
{
ShowDialogCommand = new AsyncRelayCommand(ShowDialog);
ShowCustomDialogCommand = new AsyncRelayCommand(ShowCustomDialog);
Modes = new ObservableCollection<DialogMode>(Enum.GetValues<DialogMode>());
Buttons = new ObservableCollection<DialogButton>(Enum.GetValues<DialogButton>());
}
private async Task ShowDialog()
{
var vm = new PlainDialogViewModel();
if (IsWindow)
{
DefaultResult = await Dialog.ShowModalAsync<PlainDialog, PlainDialogViewModel>(
vm,
"Please select a date",
SelectedMode,
SelectedButton);
Date = vm.Date;
}
else
{
if (IsModal)
{
DefaultResult = await OverlayDialog.ShowModalAsync<PlainDialog, PlainDialogViewModel>(
vm,
IsGlobal ? null : "LocalHost",
"Please select a date",
SelectedMode,
SelectedButton
);
Date = vm.Date;
}
else
{
OverlayDialog.Show<PlainDialog, PlainDialogViewModel>(
new PlainDialogViewModel(),
IsGlobal ? null : "LocalHost",
"Please select a date",
SelectedMode,
SelectedButton);
}
}
}
private async Task ShowCustomDialog()
{
var vm = new DialogWithActionViewModel();
if (IsWindow)
{
Result = await Dialog.ShowCustomModalAsync<DialogWithAction, DialogWithActionViewModel, bool>(
vm);
Date = vm.Date;
}
else
{
if (IsModal)
{
Result = await OverlayDialog.ShowCustomModalAsync<DialogWithAction, DialogWithActionViewModel, bool>(
vm, IsGlobal ? null : "LocalHost");
Date = vm.Date;
}
else
{
OverlayDialog.ShowCustom<DialogWithAction, DialogWithActionViewModel>(new DialogWithActionViewModel(),
IsGlobal ? null : "LocalHost");
}
}
}
}

View File

@@ -28,6 +28,7 @@ public class MainViewViewModel : ViewModelBase
MenuKeys.MenuKeyBadge => new BadgeDemoViewModel(),
MenuKeys.MenuKeyBanner => new BannerDemoViewModel(),
MenuKeys.MenuKeyButtonGroup => new ButtonGroupDemoViewModel(),
MenuKeys.MenuKeyDialog => new DialogDemoViewModel(),
MenuKeys.MenuKeyDivider => new DividerDemoViewModel(),
MenuKeys.MenuKeyDualBadge => new DualBadgeDemoViewModel(),
MenuKeys.MenuKeyEnumSelector => new EnumSelectorDemoViewModel(),

View File

@@ -14,6 +14,7 @@ public class MenuViewModel: ViewModelBase
new() { MenuHeader = "Controls", IsSeparator = true },
new() { MenuHeader = "Badge", Key = MenuKeys.MenuKeyBadge },
new() { MenuHeader = "Banner", Key = MenuKeys.MenuKeyBanner },
new() { MenuHeader = "Dialog", Key = MenuKeys.MenuKeyDialog },
new() { MenuHeader = "ButtonGroup", Key = MenuKeys.MenuKeyButtonGroup, Status = "Updated"},
new() { MenuHeader = "Divider", Key = MenuKeys.MenuKeyDivider },
new() { MenuHeader = "DualBadge", Key = MenuKeys.MenuKeyDualBadge },

View File

@@ -61,7 +61,14 @@ public class MessageBoxDemoViewModel: ObservableObject
_title = value ? "Ursa MessageBox" : string.Empty;
}
}
private bool _useOverlay;
public bool UseOverlay
{
get => _useOverlay;
set => SetProperty(ref _useOverlay, value);
}
@@ -80,26 +87,46 @@ public class MessageBoxDemoViewModel: ObservableObject
private async Task OnDefaultMessageAsync()
{
Result = await MessageBox.ShowAsync(_message, _title, icon: SelectedIcon);
if (UseOverlay)
{
Result = await MessageBox.ShowOverlayAsync(_message, _title, icon: SelectedIcon);
}
else
{
Result = await MessageBox.ShowAsync(_message, _title, icon: SelectedIcon);
}
}
private async Task OnOkAsync()
{
Result = await MessageBox.ShowAsync(_message, _title, icon: SelectedIcon, button:MessageBoxButton.OK);
await Show(MessageBoxButton.OK);
}
private async Task OnYesNoAsync()
{
Result = await MessageBox.ShowAsync(_message, _title, icon: SelectedIcon, button: MessageBoxButton.YesNo);
await Show(MessageBoxButton.YesNo);
}
private async Task OnYesNoCancelAsync()
{
Result = await MessageBox.ShowAsync(_message, _title, icon: SelectedIcon, button: MessageBoxButton.YesNoCancel);
await Show(MessageBoxButton.YesNoCancel);
}
private async Task OnOkCancelAsync()
{
Result = await MessageBox.ShowAsync(_message, _title, icon: SelectedIcon, button:MessageBoxButton.OKCancel);
await Show(MessageBoxButton.OK);
}
private async Task Show(MessageBoxButton button)
{
if (UseOverlay)
{
Result = await MessageBox.ShowOverlayAsync(_message, _title, icon: SelectedIcon, button:button);
}
else
{
Result = await MessageBox.ShowAsync(_message, _title, icon: SelectedIcon, button:button);
}
}
}

View File

@@ -93,6 +93,7 @@
<converters:ViewLocator />
</ContentControl.ContentTemplate>
</ContentControl>
<u:OverlayDialogHost Grid.Row="0" Grid.Column="0" Grid.RowSpan="2" Grid.ColumnSpan="2"/>
</Grid>
</UserControl>