Merge pull request #103 from irihitech/issue/102
Dialog CanDragMove/CanClose attached property.
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Ursa.Demo.Dialogs"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:u="https://irihi.tech/ursa"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
d:DesignHeight="450"
|
||||
@@ -30,6 +31,7 @@
|
||||
HorizontalAlignment="Right"
|
||||
Orientation="Horizontal"
|
||||
Spacing="8">
|
||||
<Rectangle Width="10" Height="10" Fill="Red" u:DialogControlBase.CanClose="True"></Rectangle>
|
||||
<Button Command="{Binding DialogCommand}" Content="Dialog" />
|
||||
<Button Command="{Binding OKCommand}" Content="OK" />
|
||||
<Button Command="{Binding CancelCommand}" Content="Cancel" />
|
||||
|
||||
@@ -36,8 +36,7 @@
|
||||
OnContent="Modal" />
|
||||
<ToggleSwitch
|
||||
Content="ClickOnMaskToClose"
|
||||
IsChecked="{Binding CanCloseMaskToClose}"
|
||||
IsVisible="{Binding #defaultModal.IsChecked}"
|
||||
IsChecked="{Binding CanLightDismiss}"
|
||||
OffContent="No"
|
||||
OnContent="Yes" />
|
||||
<StackPanel Orientation="Horizontal">
|
||||
@@ -81,8 +80,7 @@
|
||||
OnContent="Modal" />
|
||||
<ToggleSwitch
|
||||
Content="ClickOnMaskToClose"
|
||||
IsChecked="{Binding CanCloseMaskToClose}"
|
||||
IsVisible="{Binding #modal.IsChecked}"
|
||||
IsChecked="{Binding CanLightDismiss}"
|
||||
OffContent="No"
|
||||
OnContent="Yes" />
|
||||
<Button Command="{Binding ShowCustomDialogCommand}" Content="Show Dialog" />
|
||||
|
||||
@@ -23,13 +23,13 @@
|
||||
OffContent="Local"
|
||||
OnContent="Global" />
|
||||
<ToggleSwitch
|
||||
Content="ShowMask"
|
||||
IsChecked="{Binding ShowMask}"
|
||||
Content="Modal"
|
||||
IsChecked="{Binding IsModal}"
|
||||
OffContent="No"
|
||||
OnContent="Yes" />
|
||||
<ToggleSwitch
|
||||
Content="ClickOnMaskToClose"
|
||||
IsChecked="{Binding CanCloseMaskToClose}"
|
||||
Content="CanLightDismiss"
|
||||
IsChecked="{Binding CanLightDismiss}"
|
||||
OffContent="No"
|
||||
OnContent="Yes" />
|
||||
<StackPanel Orientation="Horizontal">
|
||||
@@ -56,13 +56,13 @@
|
||||
OffContent="Local"
|
||||
OnContent="Global" />
|
||||
<ToggleSwitch
|
||||
Content="ClickOnMaskToClose"
|
||||
IsChecked="{Binding CanCloseMaskToClose}"
|
||||
Content="CanLightDismiss"
|
||||
IsChecked="{Binding CanLightDismiss}"
|
||||
OffContent="No"
|
||||
OnContent="Yes" />
|
||||
<ToggleSwitch
|
||||
Content="ShowMask"
|
||||
IsChecked="{Binding ShowMask}"
|
||||
Content="Modal"
|
||||
IsChecked="{Binding IsModal}"
|
||||
OffContent="No"
|
||||
OnContent="Yes" />
|
||||
<Button Command="{Binding ShowCustomDialogCommand}" Content="Show Custom Drawer" />
|
||||
|
||||
@@ -55,11 +55,11 @@ public class DialogDemoViewModel: ObservableObject
|
||||
set => SetProperty(ref _isModal, value);
|
||||
}
|
||||
|
||||
private bool _canCloseMaskToClose;
|
||||
public bool CanCloseMaskToClose
|
||||
private bool _canLightDismiss;
|
||||
public bool CanLightDismiss
|
||||
{
|
||||
get => _canCloseMaskToClose;
|
||||
set => SetProperty(ref _canCloseMaskToClose, value);
|
||||
get => _canLightDismiss;
|
||||
set => SetProperty(ref _canLightDismiss, value);
|
||||
}
|
||||
|
||||
private DialogResult? _defaultResult;
|
||||
@@ -118,7 +118,7 @@ public class DialogDemoViewModel: ObservableObject
|
||||
Title = "Please select a date",
|
||||
Mode = SelectedMode,
|
||||
Buttons = SelectedButton,
|
||||
CanClickOnMaskToClose = CanCloseMaskToClose,
|
||||
CanLightDismiss = CanLightDismiss,
|
||||
HorizontalAnchor = HorizontalPosition.Right,
|
||||
HorizontalOffset = 50,
|
||||
VerticalAnchor = VerticalPosition.Top,
|
||||
@@ -136,7 +136,8 @@ public class DialogDemoViewModel: ObservableObject
|
||||
{
|
||||
Title = "Please select a date",
|
||||
Mode = SelectedMode,
|
||||
Buttons = SelectedButton
|
||||
Buttons = SelectedButton,
|
||||
CanLightDismiss = CanLightDismiss,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -169,14 +170,15 @@ public class DialogDemoViewModel: ObservableObject
|
||||
Result = await OverlayDialog.ShowCustomModal<DialogWithAction, DialogWithActionViewModel, bool>(
|
||||
vm, IsGlobal ? null : "LocalHost", options: new OverlayDialogOptions()
|
||||
{
|
||||
CanClickOnMaskToClose = CanCloseMaskToClose,
|
||||
CanLightDismiss = CanLightDismiss,
|
||||
});
|
||||
Date = vm.Date;
|
||||
}
|
||||
else
|
||||
{
|
||||
OverlayDialog.ShowCustom<DialogWithAction, DialogWithActionViewModel>(new DialogWithActionViewModel(),
|
||||
IsGlobal ? null : "LocalHost");
|
||||
IsGlobal ? null : "LocalHost",
|
||||
options: new OverlayDialogOptions{ CanLightDismiss = CanLightDismiss });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,10 +20,10 @@ public partial class DrawerDemoViewModel: ObservableObject
|
||||
[ObservableProperty] private Position _selectedPosition;
|
||||
[ObservableProperty] private DialogButton _selectedButton;
|
||||
[ObservableProperty] private bool _isGlobal;
|
||||
[ObservableProperty] private bool _canCloseMaskToClose;
|
||||
[ObservableProperty] private bool _canLightDismiss;
|
||||
[ObservableProperty] private DialogResult? _defaultResult;
|
||||
[ObservableProperty] private bool _result;
|
||||
[ObservableProperty] private bool _showMask;
|
||||
[ObservableProperty] private bool _isModal;
|
||||
[ObservableProperty] private DateTime? _date;
|
||||
|
||||
|
||||
@@ -36,32 +36,60 @@ public partial class DrawerDemoViewModel: ObservableObject
|
||||
private async Task ShowDefaultDialog()
|
||||
{
|
||||
var vm = new PlainDialogViewModel();
|
||||
DefaultResult = await Drawer.Show<PlainDialog, PlainDialogViewModel>(
|
||||
vm,
|
||||
IsGlobal ? null : "LocalHost",
|
||||
new DefaultDrawerOptions()
|
||||
{
|
||||
Title = "Please select a date",
|
||||
Position = SelectedPosition,
|
||||
Buttons = SelectedButton,
|
||||
CanClickOnMaskToClose = CanCloseMaskToClose,
|
||||
ShowMask = ShowMask,
|
||||
});
|
||||
Date = vm.Date;
|
||||
if (IsModal)
|
||||
{
|
||||
DefaultResult = await Drawer.ShowModal<PlainDialog, PlainDialogViewModel>(
|
||||
vm,
|
||||
IsGlobal ? null : "LocalHost",
|
||||
new DrawerOptions()
|
||||
{
|
||||
Title = "Please select a date",
|
||||
Position = SelectedPosition,
|
||||
Buttons = SelectedButton,
|
||||
CanLightDismiss = CanLightDismiss,
|
||||
});
|
||||
Date = vm.Date;
|
||||
}
|
||||
else
|
||||
{
|
||||
Drawer.Show<PlainDialog, PlainDialogViewModel>(
|
||||
vm,
|
||||
IsGlobal ? null : "LocalHost",
|
||||
new DrawerOptions()
|
||||
{
|
||||
Title = "Please select a date",
|
||||
Position = SelectedPosition,
|
||||
Buttons = SelectedButton,
|
||||
CanLightDismiss = CanLightDismiss,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ShowCustomDrawer()
|
||||
{
|
||||
var vm = new DialogWithActionViewModel();
|
||||
Result = await Drawer.ShowCustom<DialogWithAction, DialogWithActionViewModel, bool>(
|
||||
vm,
|
||||
IsGlobal ? null : "LocalHost",
|
||||
new CustomDrawerOptions()
|
||||
{
|
||||
Position = SelectedPosition,
|
||||
CanClickOnMaskToClose = CanCloseMaskToClose,
|
||||
ShowMask = ShowMask,
|
||||
});
|
||||
Date = vm.Date;
|
||||
if (IsModal)
|
||||
{
|
||||
Result = await Drawer.ShowCustomModal<DialogWithAction, DialogWithActionViewModel, bool>(
|
||||
vm,
|
||||
IsGlobal ? null : "LocalHost",
|
||||
new DrawerOptions()
|
||||
{
|
||||
Position = SelectedPosition,
|
||||
CanLightDismiss = CanLightDismiss,
|
||||
});
|
||||
Date = vm.Date;
|
||||
}
|
||||
else
|
||||
{
|
||||
Drawer.ShowCustom<DialogWithAction, DialogWithActionViewModel>(
|
||||
vm,
|
||||
IsGlobal ? null : "LocalHost",
|
||||
new DrawerOptions()
|
||||
{
|
||||
Position = SelectedPosition,
|
||||
CanLightDismiss = CanLightDismiss,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,81 +16,89 @@
|
||||
<Design.DataContext>
|
||||
<vm:MainViewViewModel />
|
||||
</Design.DataContext>
|
||||
<Panel>
|
||||
<Grid
|
||||
Classes.Blur="{Binding #host.HasModal}"
|
||||
ColumnDefinitions="Auto, *"
|
||||
RowDefinitions="Auto, *">
|
||||
<Grid.Styles>
|
||||
<Style Selector="Grid.Blur">
|
||||
<Setter Property="Effect" Value="blur(20)" />
|
||||
</Style>
|
||||
</Grid.Styles>
|
||||
<Border
|
||||
Grid.RowSpan="2"
|
||||
Padding="8,4"
|
||||
VerticalAlignment="Stretch"
|
||||
Theme="{DynamicResource CardBorder}">
|
||||
<u:NavigationMenu ItemsSource="{Binding Menus.MenuItems}" ShowCollapseButton="True">
|
||||
<u:NavigationMenu.Header>
|
||||
<TextBlock
|
||||
Classes="H4"
|
||||
Text="Ursa"
|
||||
Theme="{DynamicResource TitleTextBlock}" />
|
||||
</u:NavigationMenu.Header>
|
||||
<u:NavigationMenu.Icon>
|
||||
<Image
|
||||
Width="48"
|
||||
Height="48"
|
||||
RenderOptions.BitmapInterpolationMode="HighQuality"
|
||||
Source="../Assets/Ursa.ico" />
|
||||
</u:NavigationMenu.Icon>
|
||||
<u:NavigationMenu.ItemTemplate>
|
||||
<converters:MenuDataTemplateSelector>
|
||||
<converters:MenuDataTemplateSelector.MenuTemplate>
|
||||
<DataTemplate DataType="vm:MenuItemViewModel">
|
||||
<u:NavigationMenuItem
|
||||
Command="{Binding ActivateCommand}"
|
||||
Header="{Binding}"
|
||||
ItemsSource="{Binding Children}">
|
||||
<u:NavigationMenuItem.HeaderTemplate>
|
||||
<DataTemplate x:DataType="vm:MenuItemViewModel">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock HorizontalAlignment="Left" Text="{Binding MenuHeader}" />
|
||||
<u:Badge
|
||||
Margin="8,0,0,0"
|
||||
HorizontalAlignment="Left"
|
||||
BadgeContent="{Binding Status}"
|
||||
CornerPosition="TopRight" />
|
||||
</StackPanel>
|
||||
|
||||
<Grid ColumnDefinitions="Auto, *" RowDefinitions="Auto, *">
|
||||
<Border
|
||||
Grid.RowSpan="2"
|
||||
Padding="8,4"
|
||||
VerticalAlignment="Stretch"
|
||||
Theme="{DynamicResource CardBorder}">
|
||||
<u:NavigationMenu ItemsSource="{Binding Menus.MenuItems}" ShowCollapseButton="True">
|
||||
<u:NavigationMenu.Header>
|
||||
<TextBlock
|
||||
Classes="H4"
|
||||
Text="Ursa"
|
||||
Theme="{DynamicResource TitleTextBlock}" />
|
||||
</u:NavigationMenu.Header>
|
||||
<u:NavigationMenu.Icon>
|
||||
<Image
|
||||
Width="48"
|
||||
Height="48"
|
||||
RenderOptions.BitmapInterpolationMode="HighQuality"
|
||||
Source="../Assets/Ursa.ico" />
|
||||
</u:NavigationMenu.Icon>
|
||||
<u:NavigationMenu.ItemTemplate>
|
||||
<converters:MenuDataTemplateSelector>
|
||||
<converters:MenuDataTemplateSelector.MenuTemplate>
|
||||
<DataTemplate DataType="vm:MenuItemViewModel">
|
||||
<u:NavigationMenuItem
|
||||
Command="{Binding ActivateCommand}"
|
||||
Header="{Binding}"
|
||||
ItemsSource="{Binding Children}">
|
||||
<u:NavigationMenuItem.HeaderTemplate>
|
||||
<DataTemplate x:DataType="vm:MenuItemViewModel">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock HorizontalAlignment="Left" Text="{Binding MenuHeader}" />
|
||||
<u:Badge
|
||||
Margin="8,0,0,0"
|
||||
HorizontalAlignment="Left"
|
||||
BadgeContent="{Binding Status}"
|
||||
CornerPosition="TopRight" />
|
||||
</StackPanel>
|
||||
|
||||
</DataTemplate>
|
||||
</u:NavigationMenuItem.HeaderTemplate>
|
||||
<u:NavigationMenuItem.Icon>
|
||||
<Border
|
||||
Width="10"
|
||||
Height="10"
|
||||
Background="{DynamicResource SemiBlue6}"
|
||||
CornerRadius="3" />
|
||||
</u:NavigationMenuItem.Icon>
|
||||
</u:NavigationMenuItem>
|
||||
</DataTemplate>
|
||||
</converters:MenuDataTemplateSelector.MenuTemplate>
|
||||
<converters:MenuDataTemplateSelector.SeparatorTemplate>
|
||||
<DataTemplate DataType="vm:MenuItemViewModel">
|
||||
<u:NavigationMenuSeparator Header="{Binding MenuHeader}" />
|
||||
</DataTemplate>
|
||||
</converters:MenuDataTemplateSelector.SeparatorTemplate>
|
||||
</converters:MenuDataTemplateSelector>
|
||||
</u:NavigationMenu.ItemTemplate>
|
||||
</u:NavigationMenu>
|
||||
</Border>
|
||||
<u:ThemeToggleButton
|
||||
Grid.Row="0"
|
||||
Grid.Column="1"
|
||||
HorizontalAlignment="Right"/>
|
||||
<ContentControl
|
||||
Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
Margin="12"
|
||||
Content="{Binding Content}">
|
||||
<ContentControl.ContentTemplate>
|
||||
<converters:ViewLocator />
|
||||
</ContentControl.ContentTemplate>
|
||||
</ContentControl>
|
||||
<u:OverlayDialogHost Grid.Row="0" Grid.Column="0" Grid.RowSpan="2" Grid.ColumnSpan="2" SnapThickness="20"/>
|
||||
</Grid>
|
||||
|
||||
</DataTemplate>
|
||||
</u:NavigationMenuItem.HeaderTemplate>
|
||||
<u:NavigationMenuItem.Icon>
|
||||
<Border
|
||||
Width="10"
|
||||
Height="10"
|
||||
Background="{DynamicResource SemiBlue6}"
|
||||
CornerRadius="3" />
|
||||
</u:NavigationMenuItem.Icon>
|
||||
</u:NavigationMenuItem>
|
||||
</DataTemplate>
|
||||
</converters:MenuDataTemplateSelector.MenuTemplate>
|
||||
<converters:MenuDataTemplateSelector.SeparatorTemplate>
|
||||
<DataTemplate DataType="vm:MenuItemViewModel">
|
||||
<u:NavigationMenuSeparator Header="{Binding MenuHeader}" />
|
||||
</DataTemplate>
|
||||
</converters:MenuDataTemplateSelector.SeparatorTemplate>
|
||||
</converters:MenuDataTemplateSelector>
|
||||
</u:NavigationMenu.ItemTemplate>
|
||||
</u:NavigationMenu>
|
||||
</Border>
|
||||
<u:ThemeToggleButton
|
||||
Grid.Row="0"
|
||||
Grid.Column="1"
|
||||
HorizontalAlignment="Right" />
|
||||
<ContentControl
|
||||
Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
Margin="12"
|
||||
Content="{Binding Content}">
|
||||
<ContentControl.ContentTemplate>
|
||||
<converters:ViewLocator />
|
||||
</ContentControl.ContentTemplate>
|
||||
</ContentControl>
|
||||
</Grid>
|
||||
<u:OverlayDialogHost Name="host" SnapThickness="20" />
|
||||
</Panel>
|
||||
</UserControl>
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
Title="Ursa.PrismDialogDemo">
|
||||
<Grid>
|
||||
<StackPanel>
|
||||
<Button Click="Button_OnClick">Show Dialog</Button>
|
||||
<Button Click="DialogButton_OnClick">Show Dialog</Button>
|
||||
<Button Click="DrawerButton_OnClick"></Button>
|
||||
</StackPanel>
|
||||
<u:OverlayDialogHost/>
|
||||
</Grid>
|
||||
|
||||
@@ -7,15 +7,22 @@ namespace Ursa.PrismDialogDemo;
|
||||
|
||||
public partial class MainWindow : Window
|
||||
{
|
||||
private IUrsaOverlayDialogService _ursa;
|
||||
public MainWindow(IUrsaOverlayDialogService ursa)
|
||||
private IUrsaOverlayDialogService _dialogService;
|
||||
private IUrsaDrawerService _drawerService;
|
||||
public MainWindow(IUrsaOverlayDialogService dialogService, IUrsaDrawerService drawerService)
|
||||
{
|
||||
InitializeComponent();
|
||||
_ursa = ursa;
|
||||
_dialogService = dialogService;
|
||||
_drawerService = drawerService;
|
||||
}
|
||||
|
||||
private void Button_OnClick(object? sender, RoutedEventArgs e)
|
||||
private void DialogButton_OnClick(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
_ursa.ShowModal("Default", null, null, null);
|
||||
_dialogService.ShowModal("Default", null, null, null);
|
||||
}
|
||||
|
||||
private void DrawerButton_OnClick(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
_drawerService.ShowModal("Default", null, null, null);
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,8 @@ namespace Ursa.PrismExtension;
|
||||
|
||||
public interface IUrsaDrawerService
|
||||
{
|
||||
public Task<DialogResult> ShowDrawer(string viewName, object? vm, string? hostId = null, DefaultDrawerOptions? options = null);
|
||||
public Task<TResult?> ShowCustomDrawer<TResult>(string viewName, object? vm, string? hostId = null, CustomDrawerOptions? options = null);
|
||||
public void Show(string viewName, object? vm, string? hostId = null, DrawerOptions? options = null);
|
||||
public void ShowCustom<TResult>(string viewName, object? vm, string? hostId = null, DrawerOptions? options = null);
|
||||
public Task<DialogResult> ShowModal(string viewName, object? vm, string? hostId = null, DrawerOptions? options = null);
|
||||
public Task<TResult?> ShowCustomModal<TResult>(string viewName, object? vm, string? hostId = null, DrawerOptions? options = null);
|
||||
}
|
||||
@@ -7,16 +7,27 @@ namespace Ursa.PrismExtension;
|
||||
|
||||
public class UrsaDrawerService(IContainerExtension container): IUrsaDrawerService
|
||||
{
|
||||
public Task<DialogResult> ShowDrawer(string viewName, object? vm, string? hostId = null, DefaultDrawerOptions? options = null)
|
||||
public void Show(string viewName, object? vm, string? hostId = null, DrawerOptions? options = null)
|
||||
{
|
||||
var v = container.Resolve<Control>(UrsaDialogServiceExtension.UrsaDialogViewPrefix + viewName);
|
||||
return Drawer.Show(v, vm, hostId, options);
|
||||
Drawer.Show(v, vm, hostId, options);
|
||||
}
|
||||
|
||||
public Task<TResult?> ShowCustomDrawer<TResult>(string viewName, object? vm, string? hostId = null,
|
||||
CustomDrawerOptions? options = null)
|
||||
|
||||
public void ShowCustom<TResult>(string viewName, object? vm, string? hostId = null, DrawerOptions? options = null)
|
||||
{
|
||||
var v = container.Resolve<Control>(UrsaDialogServiceExtension.UrsaDialogViewPrefix + viewName);
|
||||
return Drawer.ShowCustom<TResult?>(v, vm, hostId, options);
|
||||
Drawer.ShowCustom(v, vm, hostId, options);
|
||||
}
|
||||
|
||||
public Task<DialogResult> ShowModal(string viewName, object? vm, string? hostId = null, DrawerOptions? options = null)
|
||||
{
|
||||
var v = container.Resolve<Control>(UrsaDialogServiceExtension.UrsaDialogViewPrefix + viewName);
|
||||
return Drawer.ShowModal(v, vm, hostId, options);
|
||||
}
|
||||
|
||||
public Task<TResult?> ShowCustomModal<TResult>(string viewName, object? vm, string? hostId = null, DrawerOptions? options = null)
|
||||
{
|
||||
var v = container.Resolve<Control>(UrsaDialogServiceExtension.UrsaDialogViewPrefix + viewName);
|
||||
return Drawer.ShowCustomModal<TResult?>(v, vm, hostId, options);
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,10 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Metadata;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.LogicalTree;
|
||||
using Irihi.Avalonia.Shared.Helpers;
|
||||
using Ursa.Common;
|
||||
using Ursa.Controls.OverlayShared;
|
||||
@@ -13,12 +15,12 @@ namespace Ursa.Controls;
|
||||
[TemplatePart(PART_CloseButton, typeof(Button))]
|
||||
[TemplatePart(PART_TitleArea, typeof(Panel))]
|
||||
[PseudoClasses(PC_Modal)]
|
||||
public abstract class DialogControlBase: OverlayFeedbackElement
|
||||
public abstract class DialogControlBase : OverlayFeedbackElement
|
||||
{
|
||||
public const string PART_CloseButton = "PART_CloseButton";
|
||||
public const string PART_TitleArea = "PART_TitleArea";
|
||||
public const string PC_Modal = ":modal";
|
||||
|
||||
|
||||
internal HorizontalPosition HorizontalAnchor { get; set; } = HorizontalPosition.Center;
|
||||
internal VerticalPosition VerticalAnchor { get; set; } = VerticalPosition.Center;
|
||||
internal HorizontalPosition ActualHorizontalAnchor { get; set; }
|
||||
@@ -27,19 +29,18 @@ public abstract class DialogControlBase: OverlayFeedbackElement
|
||||
internal double? VerticalOffset { get; set; }
|
||||
internal double? HorizontalOffsetRatio { get; set; }
|
||||
internal double? VerticalOffsetRatio { get; set; }
|
||||
internal bool CanClickOnMaskToClose { get; set; }
|
||||
internal bool CanLightDismiss { get; set; }
|
||||
|
||||
internal bool CanDragMove { get; set; }
|
||||
|
||||
protected internal Button? _closeButton;
|
||||
private Panel? _titleArea;
|
||||
|
||||
internal void SetAsModal(bool modal)
|
||||
{
|
||||
PseudoClasses.Set(PC_Modal, modal);
|
||||
}
|
||||
|
||||
public static readonly RoutedEvent<DialogLayerChangeEventArgs> LayerChangedEvent = RoutedEvent.Register<CustomDialogControl, DialogLayerChangeEventArgs>(
|
||||
nameof(LayerChanged), RoutingStrategies.Bubble);
|
||||
|
||||
#region Layer Management
|
||||
|
||||
public static readonly RoutedEvent<DialogLayerChangeEventArgs> LayerChangedEvent =
|
||||
RoutedEvent.Register<CustomDialogControl, DialogLayerChangeEventArgs>(
|
||||
nameof(LayerChanged), RoutingStrategies.Bubble);
|
||||
|
||||
public event EventHandler<DialogLayerChangeEventArgs> LayerChanged
|
||||
{
|
||||
add => AddHandler(LayerChangedEvent, value);
|
||||
@@ -54,35 +55,133 @@ public abstract class DialogControlBase: OverlayFeedbackElement
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region DragMove AttachedPropert
|
||||
|
||||
public static readonly AttachedProperty<bool> CanDragMoveProperty =
|
||||
AvaloniaProperty.RegisterAttached<DialogControlBase, InputElement, bool>("CanDragMove");
|
||||
|
||||
public static void SetCanDragMove(InputElement obj, bool value) => obj.SetValue(CanDragMoveProperty, value);
|
||||
public static bool GetCanDragMove(InputElement obj) => obj.GetValue(CanDragMoveProperty);
|
||||
|
||||
private static void OnCanDragMoveChanged(InputElement arg1, AvaloniaPropertyChangedEventArgs<bool> arg2)
|
||||
{
|
||||
if (arg2.NewValue.Value)
|
||||
{
|
||||
arg1.AddHandler(PointerPressedEvent, OnPointerPressed, RoutingStrategies.Bubble);
|
||||
arg1.AddHandler(PointerMovedEvent, OnPointerMoved, RoutingStrategies.Bubble);
|
||||
arg1.AddHandler(PointerReleasedEvent, OnPointerReleased, RoutingStrategies.Bubble);
|
||||
}
|
||||
else
|
||||
{
|
||||
arg1.RemoveHandler(PointerPressedEvent, OnPointerPressed);
|
||||
arg1.RemoveHandler(PointerMovedEvent, OnPointerMoved);
|
||||
arg1.RemoveHandler(PointerReleasedEvent, OnPointerReleased);
|
||||
}
|
||||
|
||||
void OnPointerPressed(InputElement sender, PointerPressedEventArgs e)
|
||||
{
|
||||
if (sender.FindLogicalAncestorOfType<DialogControlBase>() is { } dialog)
|
||||
{
|
||||
e.Source = dialog;
|
||||
}
|
||||
}
|
||||
|
||||
void OnPointerMoved(InputElement sender, PointerEventArgs e)
|
||||
{
|
||||
if (sender.FindLogicalAncestorOfType<DialogControlBase>() is { } dialog)
|
||||
{
|
||||
e.Source = dialog;
|
||||
}
|
||||
}
|
||||
|
||||
void OnPointerReleased(InputElement sender, PointerReleasedEventArgs e)
|
||||
{
|
||||
if (sender.FindLogicalAncestorOfType<DialogControlBase>() is { } dialog)
|
||||
{
|
||||
e.Source = dialog;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Close AttachedProperty
|
||||
|
||||
public static readonly AttachedProperty<bool> CanCloseProperty =
|
||||
AvaloniaProperty.RegisterAttached<DialogControlBase, InputElement, bool>("CanClose");
|
||||
|
||||
public static void SetCanClose(InputElement obj, bool value) => obj.SetValue(CanCloseProperty, value);
|
||||
public static bool GetCanClose(InputElement obj) => obj.GetValue(CanCloseProperty);
|
||||
private static void OnCanCloseChanged(InputElement arg1, AvaloniaPropertyChangedEventArgs<bool> arg2)
|
||||
{
|
||||
if (arg2.NewValue.Value)
|
||||
{
|
||||
arg1.AddHandler(PointerPressedEvent, OnPointerPressed, RoutingStrategies.Bubble);
|
||||
}
|
||||
void OnPointerPressed(InputElement sender, PointerPressedEventArgs e)
|
||||
{
|
||||
if (sender.FindLogicalAncestorOfType<DialogControlBase>() is { } dialog)
|
||||
{
|
||||
dialog.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
static DialogControlBase()
|
||||
{
|
||||
CanDragMoveProperty.Changed.AddClassHandler<InputElement, bool>(OnCanDragMoveChanged);
|
||||
CanCloseProperty.Changed.AddClassHandler<InputElement, bool>(OnCanCloseChanged);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||
{
|
||||
base.OnApplyTemplate(e);
|
||||
_titleArea?.RemoveHandler(PointerMovedEvent, OnTitlePointerMove);
|
||||
_titleArea?.RemoveHandler(PointerPressedEvent, OnTitlePointerPressed);
|
||||
_titleArea?.RemoveHandler(PointerReleasedEvent, OnTitlePointerRelease);
|
||||
_titleArea = e.NameScope.Find<Panel>(PART_TitleArea);
|
||||
_titleArea?.AddHandler(PointerMovedEvent, OnTitlePointerMove, RoutingStrategies.Bubble);
|
||||
_titleArea?.AddHandler(PointerPressedEvent, OnTitlePointerPressed, RoutingStrategies.Bubble);
|
||||
_titleArea?.AddHandler(PointerReleasedEvent, OnTitlePointerRelease, RoutingStrategies.Bubble);
|
||||
if (CanDragMove)
|
||||
{
|
||||
_titleArea?.RemoveHandler(PointerMovedEvent, OnTitlePointerMove);
|
||||
_titleArea?.RemoveHandler(PointerPressedEvent, OnTitlePointerPressed);
|
||||
_titleArea?.RemoveHandler(PointerReleasedEvent, OnTitlePointerRelease);
|
||||
|
||||
_titleArea?.AddHandler(PointerMovedEvent, OnTitlePointerMove, RoutingStrategies.Bubble);
|
||||
_titleArea?.AddHandler(PointerPressedEvent, OnTitlePointerPressed, RoutingStrategies.Bubble);
|
||||
_titleArea?.AddHandler(PointerReleasedEvent, OnTitlePointerRelease, RoutingStrategies.Bubble);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_titleArea is not null) _titleArea.IsHitTestVisible = false;
|
||||
}
|
||||
|
||||
Button.ClickEvent.RemoveHandler(OnCloseButtonClick, _closeButton);
|
||||
_closeButton = e.NameScope.Find<Button>(PART_CloseButton);
|
||||
Button.ClickEvent.AddHandler(OnCloseButtonClick, _closeButton);
|
||||
}
|
||||
|
||||
private void OnTitlePointerPressed(object sender, PointerPressedEventArgs e)
|
||||
|
||||
private void OnTitlePointerPressed(InputElement sender, PointerPressedEventArgs e)
|
||||
{
|
||||
e.Source = this;
|
||||
}
|
||||
|
||||
private void OnTitlePointerMove(object sender, PointerEventArgs e)
|
||||
private void OnTitlePointerMove(InputElement sender, PointerEventArgs e)
|
||||
{
|
||||
e.Source = this;
|
||||
}
|
||||
|
||||
private void OnTitlePointerRelease(object sender, PointerReleasedEventArgs e)
|
||||
private void OnTitlePointerRelease(InputElement sender, PointerReleasedEventArgs e)
|
||||
{
|
||||
e.Source = this;
|
||||
}
|
||||
|
||||
|
||||
private void OnCloseButtonClick(object sender, RoutedEventArgs args) => Close();
|
||||
|
||||
internal void SetAsModal(bool modal)
|
||||
{
|
||||
PseudoClasses.Set(PC_Modal, modal);
|
||||
}
|
||||
}
|
||||
@@ -17,15 +17,32 @@ public enum VerticalPosition
|
||||
public class OverlayDialogOptions
|
||||
{
|
||||
internal static OverlayDialogOptions Default { get; } = new OverlayDialogOptions();
|
||||
public bool CanClickOnMaskToClose { get; set; } = false;
|
||||
public HorizontalPosition HorizontalAnchor { get; set; } = HorizontalPosition.Center;
|
||||
public VerticalPosition VerticalAnchor { get; set; } = VerticalPosition.Center;
|
||||
/// <summary>
|
||||
/// This attribute is only used when HorizontalAnchor is not Center
|
||||
/// </summary>
|
||||
public double? HorizontalOffset { get; set; } = null;
|
||||
/// <summary>
|
||||
/// This attribute is only used when VerticalAnchor is not Center
|
||||
/// </summary>
|
||||
public double? VerticalOffset { get; set; } = null;
|
||||
/// <summary>
|
||||
/// Only works for DefaultDialogControl
|
||||
/// </summary>
|
||||
public DialogMode Mode { get; set; } = DialogMode.None;
|
||||
/// <summary>
|
||||
/// Only works for DefaultDialogControl
|
||||
/// </summary>
|
||||
public DialogButton Buttons { get; set; } = DialogButton.OKCancel;
|
||||
/// <summary>
|
||||
/// Only works for DefaultDialogControl
|
||||
/// </summary>
|
||||
public string? Title { get; set; } = null;
|
||||
public bool IsCloseButtonVisible { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Only works for CustomDialogControl
|
||||
/// </summary>
|
||||
public bool ShowCloseButton { get; set; } = true;
|
||||
public bool CanLightDismiss { get; set; }
|
||||
public bool CanDragMove { get; set; } = true;
|
||||
}
|
||||
@@ -18,7 +18,7 @@ public static class OverlayDialog
|
||||
DataContext = vm,
|
||||
};
|
||||
ConfigureDefaultDialogControl(t, options);
|
||||
host?.AddDialog(t);
|
||||
host.AddDialog(t);
|
||||
}
|
||||
|
||||
public static void Show(Control control, object? vm, string? hostId = null,
|
||||
@@ -32,7 +32,7 @@ public static class OverlayDialog
|
||||
DataContext = vm,
|
||||
};
|
||||
ConfigureDefaultDialogControl(t, options);
|
||||
host?.AddDialog(t);
|
||||
host.AddDialog(t);
|
||||
|
||||
}
|
||||
|
||||
@@ -63,8 +63,8 @@ public static class OverlayDialog
|
||||
Content = new TView(),
|
||||
DataContext = vm,
|
||||
};
|
||||
ConfigureDialogControl(t, options);
|
||||
host?.AddDialog(t);
|
||||
ConfigureCustomDialogControl(t, options);
|
||||
host.AddDialog(t);
|
||||
}
|
||||
|
||||
public static void ShowCustom(Control control, object? vm, string? hostId = null,
|
||||
@@ -77,8 +77,8 @@ public static class OverlayDialog
|
||||
Content = control,
|
||||
DataContext = vm,
|
||||
};
|
||||
ConfigureDialogControl(t, options);
|
||||
host?.AddDialog(t);
|
||||
ConfigureCustomDialogControl(t, options);
|
||||
host.AddDialog(t);
|
||||
}
|
||||
|
||||
public static void ShowCustom(object? vm, string? hostId = null,
|
||||
@@ -94,7 +94,7 @@ public static class OverlayDialog
|
||||
Content = view,
|
||||
DataContext = vm,
|
||||
};
|
||||
ConfigureDialogControl(t, options);
|
||||
ConfigureCustomDialogControl(t, options);
|
||||
host.AddDialog(t);
|
||||
}
|
||||
|
||||
@@ -110,7 +110,7 @@ public static class OverlayDialog
|
||||
DataContext = vm,
|
||||
};
|
||||
ConfigureDefaultDialogControl(t, options);
|
||||
host?.AddModalDialog(t);
|
||||
host.AddModalDialog(t);
|
||||
return t.ShowAsync<DialogResult>(token);
|
||||
}
|
||||
|
||||
@@ -125,7 +125,7 @@ public static class OverlayDialog
|
||||
DataContext = vm,
|
||||
};
|
||||
ConfigureDefaultDialogControl(t, options);
|
||||
host?.AddModalDialog(t);
|
||||
host.AddModalDialog(t);
|
||||
return t.ShowAsync<DialogResult>(token);
|
||||
}
|
||||
|
||||
@@ -140,8 +140,8 @@ public static class OverlayDialog
|
||||
Content = new TView(),
|
||||
DataContext = vm,
|
||||
};
|
||||
ConfigureDialogControl(t, options);
|
||||
host?.AddModalDialog(t);
|
||||
ConfigureCustomDialogControl(t, options);
|
||||
host.AddModalDialog(t);
|
||||
return t.ShowAsync<TResult?>(token);
|
||||
}
|
||||
|
||||
@@ -155,8 +155,8 @@ public static class OverlayDialog
|
||||
Content = control,
|
||||
DataContext = vm,
|
||||
};
|
||||
ConfigureDialogControl(t, options);
|
||||
host?.AddModalDialog(t);
|
||||
ConfigureCustomDialogControl(t, options);
|
||||
host.AddModalDialog(t);
|
||||
return t.ShowAsync<TResult?>(token);
|
||||
}
|
||||
|
||||
@@ -173,12 +173,12 @@ public static class OverlayDialog
|
||||
Content = view,
|
||||
DataContext = vm,
|
||||
};
|
||||
ConfigureDialogControl(t, options);
|
||||
host?.AddModalDialog(t);
|
||||
ConfigureCustomDialogControl(t, options);
|
||||
host.AddModalDialog(t);
|
||||
return t.ShowAsync<TResult?>(token);
|
||||
}
|
||||
|
||||
private static void ConfigureDialogControl(CustomDialogControl control, OverlayDialogOptions? options)
|
||||
private static void ConfigureCustomDialogControl(CustomDialogControl control, OverlayDialogOptions? options)
|
||||
{
|
||||
options ??= OverlayDialogOptions.Default;
|
||||
control.HorizontalAnchor = options.HorizontalAnchor;
|
||||
@@ -189,9 +189,9 @@ public static class OverlayDialog
|
||||
control.HorizontalAnchor == HorizontalPosition.Center ? null : options.HorizontalOffset;
|
||||
control.VerticalOffset =
|
||||
options.VerticalAnchor == VerticalPosition.Center ? null : options.VerticalOffset;
|
||||
control.CanClickOnMaskToClose = options.CanClickOnMaskToClose;
|
||||
control.IsCloseButtonVisible = options.IsCloseButtonVisible;
|
||||
control.IsCloseButtonVisible = options.ShowCloseButton;
|
||||
control.CanLightDismiss = options.CanLightDismiss;
|
||||
control.CanDragMove = options.CanDragMove;
|
||||
}
|
||||
|
||||
private static void ConfigureDefaultDialogControl(DefaultDialogControl control, OverlayDialogOptions? options)
|
||||
@@ -205,11 +205,11 @@ public static class OverlayDialog
|
||||
control.HorizontalAnchor == HorizontalPosition.Center ? null : options.HorizontalOffset;
|
||||
control.VerticalOffset =
|
||||
options.VerticalAnchor == VerticalPosition.Center ? null : options.VerticalOffset;
|
||||
control.CanClickOnMaskToClose = options.CanClickOnMaskToClose;
|
||||
control.Mode = options.Mode;
|
||||
control.Buttons = options.Buttons;
|
||||
control.Title = options.Title;
|
||||
control.CanLightDismiss = options.CanLightDismiss;
|
||||
control.CanDragMove = options.CanDragMove;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -7,11 +7,11 @@ namespace Ursa.Controls;
|
||||
|
||||
public static class Drawer
|
||||
{
|
||||
public static Task<DialogResult> Show<TView, TViewModel>(TViewModel vm, string? hostId = null, DefaultDrawerOptions? options = null)
|
||||
public static void Show<TView, TViewModel>(TViewModel vm, string? hostId = null, DrawerOptions? options = null)
|
||||
where TView: Control, new()
|
||||
{
|
||||
var host = OverlayDialogManager.GetHost(hostId);
|
||||
if (host is null) return Task.FromResult(default(DialogResult));
|
||||
if (host is null) return;
|
||||
var drawer = new DefaultDrawerControl()
|
||||
{
|
||||
Content = new TView(),
|
||||
@@ -19,14 +19,13 @@ public static class Drawer
|
||||
};
|
||||
ConfigureDefaultDrawer(drawer, options);
|
||||
host.AddDrawer(drawer);
|
||||
return drawer.ShowAsync<DialogResult>();
|
||||
}
|
||||
|
||||
public static Task<DialogResult> Show(Control control, object? vm, string? hostId = null,
|
||||
DefaultDrawerOptions? options = null)
|
||||
public static void Show(Control control, object? vm, string? hostId = null,
|
||||
DrawerOptions? options = null)
|
||||
{
|
||||
var host = OverlayDialogManager.GetHost(hostId);
|
||||
if (host is null) return Task.FromResult(default(DialogResult));
|
||||
if (host is null) return;
|
||||
var drawer = new DefaultDrawerControl()
|
||||
{
|
||||
Content = control,
|
||||
@@ -34,13 +33,12 @@ public static class Drawer
|
||||
};
|
||||
ConfigureDefaultDrawer(drawer, options);
|
||||
host.AddDrawer(drawer);
|
||||
return drawer.ShowAsync<DialogResult>();
|
||||
}
|
||||
|
||||
public static Task<DialogResult> Show(object? vm, string? hostId = null, DefaultDrawerOptions? options = null)
|
||||
public static void Show(object? vm, string? hostId = null, DrawerOptions? options = null)
|
||||
{
|
||||
var host = OverlayDialogManager.GetHost(hostId);
|
||||
if (host is null) return Task.FromResult(default(DialogResult));
|
||||
if (host is null) return;
|
||||
var view = host.GetDataTemplate(vm)?.Build(vm);
|
||||
if (view is null) view = new ContentControl() { Padding = new Thickness(24) };
|
||||
view.DataContext = vm;
|
||||
@@ -51,14 +49,60 @@ public static class Drawer
|
||||
};
|
||||
ConfigureDefaultDrawer(drawer, options);
|
||||
host.AddDrawer(drawer);
|
||||
return drawer.ShowAsync<DialogResult>();
|
||||
}
|
||||
|
||||
public static Task<TResult?> ShowCustom<TView, TViewModel, TResult>(TViewModel vm, string? hostId = null, CustomDrawerOptions? options = null)
|
||||
public static Task<DialogResult> ShowModal<TView, TViewModel>(TViewModel vm, string? hostId = null, DrawerOptions? options = null)
|
||||
where TView: Control, new()
|
||||
{
|
||||
var host = OverlayDialogManager.GetHost(hostId);
|
||||
if (host is null) return Task.FromResult(default(TResult));
|
||||
if (host is null) return Task.FromResult(DialogResult.None);
|
||||
var drawer = new DefaultDrawerControl()
|
||||
{
|
||||
Content = new TView(),
|
||||
DataContext = vm,
|
||||
};
|
||||
ConfigureDefaultDrawer(drawer, options);
|
||||
host.AddModalDrawer(drawer);
|
||||
return drawer.ShowAsync<DialogResult>();
|
||||
}
|
||||
|
||||
public static Task<DialogResult> ShowModal(Control control, object? vm, string? hostId = null,
|
||||
DrawerOptions? options = null)
|
||||
{
|
||||
var host = OverlayDialogManager.GetHost(hostId);
|
||||
if (host is null) return Task.FromResult(DialogResult.None);
|
||||
var drawer = new DefaultDrawerControl()
|
||||
{
|
||||
Content = control,
|
||||
DataContext = vm,
|
||||
};
|
||||
ConfigureDefaultDrawer(drawer, options);
|
||||
host.AddModalDrawer(drawer);
|
||||
return drawer.ShowAsync<DialogResult>();
|
||||
}
|
||||
|
||||
public static Task<DialogResult> ShowModal(object? vm, string? hostId = null, DrawerOptions? options = null)
|
||||
{
|
||||
var host = OverlayDialogManager.GetHost(hostId);
|
||||
if (host is null) return Task.FromResult(DialogResult.None);
|
||||
var view = host.GetDataTemplate(vm)?.Build(vm);
|
||||
if (view is null) view = new ContentControl() { Padding = new Thickness(24) };
|
||||
view.DataContext = vm;
|
||||
var drawer = new DefaultDrawerControl()
|
||||
{
|
||||
Content = view,
|
||||
DataContext = vm,
|
||||
};
|
||||
ConfigureDefaultDrawer(drawer, options);
|
||||
host.AddModalDrawer(drawer);
|
||||
return drawer.ShowAsync<DialogResult>();
|
||||
}
|
||||
|
||||
public static void ShowCustom<TView, TViewModel>(TViewModel vm, string? hostId = null, DrawerOptions? options = null)
|
||||
where TView: Control, new()
|
||||
{
|
||||
var host = OverlayDialogManager.GetHost(hostId);
|
||||
if (host is null) return;
|
||||
var dialog = new CustomDrawerControl()
|
||||
{
|
||||
Content = new TView(),
|
||||
@@ -66,13 +110,12 @@ public static class Drawer
|
||||
};
|
||||
ConfigureCustomDrawer(dialog, options);
|
||||
host.AddDrawer(dialog);
|
||||
return dialog.ShowAsync<TResult>();
|
||||
}
|
||||
|
||||
public static Task<TResult?> ShowCustom<TResult>(Control control, object? vm, string? hostId = null, CustomDrawerOptions? options = null)
|
||||
public static void ShowCustom(Control control, object? vm, string? hostId = null, DrawerOptions? options = null)
|
||||
{
|
||||
var host = OverlayDialogManager.GetHost(hostId);
|
||||
if (host is null) return Task.FromResult(default(TResult));
|
||||
if (host is null) return;
|
||||
var dialog = new CustomDrawerControl()
|
||||
{
|
||||
Content = control,
|
||||
@@ -80,13 +123,12 @@ public static class Drawer
|
||||
};
|
||||
ConfigureCustomDrawer(dialog, options);
|
||||
host.AddDrawer(dialog);
|
||||
return dialog.ShowAsync<TResult>();
|
||||
}
|
||||
|
||||
public static Task<TResult?> ShowCustom<TResult>(object? vm, string? hostId = null, CustomDrawerOptions? options = null)
|
||||
public static void ShowCustom(object? vm, string? hostId = null, DrawerOptions? options = null)
|
||||
{
|
||||
var host = OverlayDialogManager.GetHost(hostId);
|
||||
if (host is null) return Task.FromResult(default(TResult));
|
||||
if (host is null) return;
|
||||
var view = host.GetDataTemplate(vm)?.Build(vm);
|
||||
if (view is null) view = new ContentControl() { Padding = new Thickness(24) };
|
||||
view.DataContext = vm;
|
||||
@@ -97,17 +139,59 @@ public static class Drawer
|
||||
};
|
||||
ConfigureCustomDrawer(dialog, options);
|
||||
host.AddDrawer(dialog);
|
||||
return dialog.ShowAsync<TResult>();
|
||||
}
|
||||
|
||||
|
||||
private static void ConfigureCustomDrawer(CustomDrawerControl drawer, CustomDrawerOptions? options)
|
||||
public static Task<TResult?> ShowCustomModal<TView, TViewModel, TResult>(TViewModel vm, string? hostId = null, DrawerOptions? options = null)
|
||||
where TView: Control, new()
|
||||
{
|
||||
options ??= CustomDrawerOptions.Default;
|
||||
var host = OverlayDialogManager.GetHost(hostId);
|
||||
if (host is null) return Task.FromResult<TResult?>(default);
|
||||
var dialog = new CustomDrawerControl()
|
||||
{
|
||||
Content = new TView(),
|
||||
DataContext = vm,
|
||||
};
|
||||
ConfigureCustomDrawer(dialog, options);
|
||||
host.AddModalDrawer(dialog);
|
||||
return dialog.ShowAsync<TResult?>();
|
||||
}
|
||||
|
||||
public static Task<TResult?> ShowCustomModal<TResult>(Control control, object? vm, string? hostId = null, DrawerOptions? options = null)
|
||||
{
|
||||
var host = OverlayDialogManager.GetHost(hostId);
|
||||
if (host is null) return Task.FromResult<TResult?>(default);
|
||||
var dialog = new CustomDrawerControl()
|
||||
{
|
||||
Content = control,
|
||||
DataContext = vm,
|
||||
};
|
||||
ConfigureCustomDrawer(dialog, options);
|
||||
host.AddModalDrawer(dialog);
|
||||
return dialog.ShowAsync<TResult?>();
|
||||
}
|
||||
|
||||
public static Task<TResult?> ShowCustomModal<TResult>(object? vm, string? hostId = null, DrawerOptions? options = null)
|
||||
{
|
||||
var host = OverlayDialogManager.GetHost(hostId);
|
||||
if (host is null) return Task.FromResult<TResult?>(default);
|
||||
var view = host.GetDataTemplate(vm)?.Build(vm);
|
||||
if (view is null) view = new ContentControl() { Padding = new Thickness(24) };
|
||||
view.DataContext = vm;
|
||||
var dialog = new CustomDrawerControl()
|
||||
{
|
||||
Content = view,
|
||||
DataContext = vm,
|
||||
};
|
||||
ConfigureCustomDrawer(dialog, options);
|
||||
host.AddModalDrawer(dialog);
|
||||
return dialog.ShowAsync<TResult?>();
|
||||
}
|
||||
|
||||
private static void ConfigureCustomDrawer(CustomDrawerControl drawer, DrawerOptions? options)
|
||||
{
|
||||
options ??= DrawerOptions.Default;
|
||||
drawer.Position = options.Position;
|
||||
drawer.CanClickOnMaskToClose = options.CanClickOnMaskToClose;
|
||||
drawer.IsCloseButtonVisible = options.IsCloseButtonVisible;
|
||||
drawer.ShowMask = options.ShowMask;
|
||||
drawer.IsCloseButtonVisible = options.ShowCloseButton;
|
||||
drawer.CanLightDismiss = options.CanLightDismiss;
|
||||
if (options.Position == Position.Left || options.Position == Position.Right)
|
||||
{
|
||||
@@ -121,16 +205,14 @@ public static class Drawer
|
||||
}
|
||||
}
|
||||
|
||||
private static void ConfigureDefaultDrawer(DefaultDrawerControl drawer, DefaultDrawerOptions? options)
|
||||
private static void ConfigureDefaultDrawer(DefaultDrawerControl drawer, DrawerOptions? options)
|
||||
{
|
||||
options ??= DefaultDrawerOptions.Default;
|
||||
options ??= DrawerOptions.Default;
|
||||
drawer.Position = options.Position;
|
||||
drawer.CanClickOnMaskToClose = options.CanClickOnMaskToClose;
|
||||
drawer.IsCloseButtonVisible = options.IsCloseButtonVisible;
|
||||
drawer.CanLightDismiss = options.CanLightDismiss;
|
||||
drawer.Buttons = options.Buttons;
|
||||
drawer.Title = options.Title;
|
||||
drawer.ShowMask = options.ShowMask;
|
||||
drawer.CanLightDismiss = options.CanLightDismiss;
|
||||
if (options.Position == Position.Left || options.Position == Position.Right)
|
||||
{
|
||||
drawer.MinWidth = options.MinWidth ?? 0.0;
|
||||
|
||||
@@ -15,9 +15,7 @@ namespace Ursa.Controls;
|
||||
[TemplatePart(PART_CloseButton, typeof(Button))]
|
||||
public abstract class DrawerControlBase: OverlayFeedbackElement
|
||||
{
|
||||
public const string PART_CloseButton = "PART_CloseButton";
|
||||
|
||||
internal bool CanClickOnMaskToClose { get; set; }
|
||||
public const string PART_CloseButton = "PART_CloseButton";
|
||||
|
||||
protected internal Button? _closeButton;
|
||||
|
||||
@@ -50,7 +48,6 @@ public const string PART_CloseButton = "PART_CloseButton";
|
||||
set => SetValue(IsCloseButtonVisibleProperty, value);
|
||||
}
|
||||
|
||||
protected internal bool ShowMask { get; set; }
|
||||
protected internal bool CanLightDismiss { get; set; }
|
||||
|
||||
static DrawerControlBase()
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
using Ursa.Common;
|
||||
|
||||
namespace Ursa.Controls.Options;
|
||||
|
||||
public class CustomDrawerOptions
|
||||
{
|
||||
internal static CustomDrawerOptions Default => new ();
|
||||
public Position Position { get; set; } = Position.Right;
|
||||
public bool CanClickOnMaskToClose { get; set; } = true;
|
||||
public bool CanLightDismiss { get; set; } = false;
|
||||
public bool ShowMask { get; set; } = true;
|
||||
public bool IsCloseButtonVisible { get; set; } = true;
|
||||
public double? MinWidth { get; set; } = null;
|
||||
public double? MinHeight { get; set; } = null;
|
||||
public double? MaxWidth { get; set; } = null;
|
||||
public double? MaxHeight { get; set; } = null;
|
||||
}
|
||||
@@ -2,13 +2,11 @@
|
||||
|
||||
namespace Ursa.Controls.Options;
|
||||
|
||||
public class DefaultDrawerOptions
|
||||
public class DrawerOptions
|
||||
{
|
||||
internal static DefaultDrawerOptions Default => new ();
|
||||
internal static DrawerOptions Default => new ();
|
||||
public Position Position { get; set; } = Position.Right;
|
||||
public bool CanClickOnMaskToClose { get; set; } = true;
|
||||
public bool CanLightDismiss { get; set; } = false;
|
||||
public bool ShowMask { get; set; } = true;
|
||||
public bool CanLightDismiss { get; set; } = true;
|
||||
public bool IsCloseButtonVisible { get; set; } = true;
|
||||
public double? MinWidth { get; set; } = null;
|
||||
public double? MinHeight { get; set; } = null;
|
||||
@@ -16,4 +14,5 @@ public class DefaultDrawerOptions
|
||||
public double? MaxHeight { get; set; } = null;
|
||||
public DialogButton Buttons { get; set; } = DialogButton.OKCancel;
|
||||
public string? Title { get; set; }
|
||||
public bool ShowCloseButton { get; set; } = true;
|
||||
}
|
||||
@@ -85,14 +85,14 @@ public partial class OverlayDialogHost
|
||||
PureRectangle? mask = null;
|
||||
if (control.CanLightDismiss)
|
||||
{
|
||||
CreateOverlayMask(false, control.CanLightDismiss);
|
||||
mask = CreateOverlayMask(false, control.CanLightDismiss);
|
||||
}
|
||||
if (mask is not null)
|
||||
{
|
||||
Children.Add(mask);
|
||||
}
|
||||
this.Children.Add(control);
|
||||
_layers.Add(new DialogPair(mask, control));
|
||||
_layers.Add(new DialogPair(mask, control, false));
|
||||
control.Measure(this.Bounds.Size);
|
||||
control.Arrange(new Rect(control.DesiredSize));
|
||||
SetToPosition(control);
|
||||
@@ -116,8 +116,14 @@ public partial class OverlayDialogHost
|
||||
|
||||
if (layer.Mask is not null)
|
||||
{
|
||||
await _maskDisappearAnimation.RunAsync(layer.Mask);
|
||||
Children.Remove(layer.Mask);
|
||||
|
||||
if (layer.Modal)
|
||||
{
|
||||
_modalCount--;
|
||||
HasModal = _modalCount > 0;
|
||||
await _maskDisappearAnimation.RunAsync(layer.Mask);
|
||||
}
|
||||
}
|
||||
|
||||
ResetZIndices();
|
||||
@@ -130,7 +136,7 @@ public partial class OverlayDialogHost
|
||||
/// <param name="control"></param>
|
||||
internal void AddModalDialog(DialogControlBase control)
|
||||
{
|
||||
var mask = CreateOverlayMask(true, control.CanClickOnMaskToClose);
|
||||
var mask = CreateOverlayMask(true, control.CanLightDismiss);
|
||||
_layers.Add(new DialogPair(mask, control));
|
||||
control.SetAsModal(true);
|
||||
ResetZIndices();
|
||||
@@ -142,6 +148,8 @@ public partial class OverlayDialogHost
|
||||
control.AddHandler(OverlayFeedbackElement.ClosedEvent, OnDialogControlClosing);
|
||||
control.AddHandler(DialogControlBase.LayerChangedEvent, OnDialogLayerChanged);
|
||||
_maskAppearAnimation.RunAsync(mask);
|
||||
_modalCount++;
|
||||
HasModal = _modalCount > 0;
|
||||
control.IsClosed = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,14 +15,10 @@ public partial class OverlayDialogHost
|
||||
internal async void AddDrawer(DrawerControlBase control)
|
||||
{
|
||||
PureRectangle? mask = null;
|
||||
if (control.ShowMask == false && control.CanLightDismiss)
|
||||
if (control.CanLightDismiss)
|
||||
{
|
||||
mask = CreateOverlayMask(false, true);
|
||||
}
|
||||
else if (control.ShowMask)
|
||||
{
|
||||
mask = CreateOverlayMask(control.ShowMask, control.CanClickOnMaskToClose);
|
||||
}
|
||||
_layers.Add(new DialogPair(mask, control));
|
||||
ResetZIndices();
|
||||
if(mask is not null)this.Children.Add(mask);
|
||||
@@ -40,7 +36,21 @@ public partial class OverlayDialogHost
|
||||
{
|
||||
await Task.WhenAll(animation.RunAsync(control), _maskAppearAnimation.RunAsync(mask));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
internal async void AddModalDrawer(DrawerControlBase control)
|
||||
{
|
||||
PureRectangle? mask = CreateOverlayMask(true, control.CanLightDismiss);
|
||||
_layers.Add(new DialogPair(mask, control));
|
||||
this.Children.Add(mask);
|
||||
this.Children.Add(control);
|
||||
ResetZIndices();
|
||||
control.Measure(this.Bounds.Size);
|
||||
control.Arrange(new Rect(control.DesiredSize));
|
||||
SetDrawerPosition(control);
|
||||
control.AddHandler(OverlayFeedbackElement.ClosedEvent, OnDrawerControlClosing);
|
||||
var animation = CreateAnimation(control.Bounds.Size, control.Position);
|
||||
await Task.WhenAll(animation.RunAsync(control), _maskAppearAnimation.RunAsync(mask));
|
||||
}
|
||||
|
||||
private void SetDrawerPosition(DrawerControlBase control)
|
||||
|
||||
@@ -24,13 +24,28 @@ public partial class OverlayDialogHost: Canvas
|
||||
{
|
||||
internal PureRectangle? Mask;
|
||||
internal OverlayFeedbackElement Element;
|
||||
internal bool Modal;
|
||||
|
||||
public DialogPair(PureRectangle? mask, OverlayFeedbackElement element)
|
||||
public DialogPair(PureRectangle? mask, OverlayFeedbackElement element, bool modal = true)
|
||||
{
|
||||
Mask = mask;
|
||||
Element = element;
|
||||
Modal = modal;
|
||||
}
|
||||
}
|
||||
|
||||
private int _modalCount = 0;
|
||||
|
||||
|
||||
|
||||
public static readonly DirectProperty<OverlayDialogHost, bool> HasModalProperty = AvaloniaProperty.RegisterDirect<OverlayDialogHost, bool>(
|
||||
nameof(HasModal), o => o.HasModal);
|
||||
private bool _hasModal;
|
||||
public bool HasModal
|
||||
{
|
||||
get => _hasModal;
|
||||
private set => SetAndRaise(HasModalProperty, ref _hasModal, value);
|
||||
}
|
||||
|
||||
static OverlayDialogHost()
|
||||
{
|
||||
@@ -81,7 +96,7 @@ public partial class OverlayDialogHost: Canvas
|
||||
}
|
||||
else if(canCloseOnClick)
|
||||
{
|
||||
rec.SetCurrentValue(Shape.FillProperty, Brushes.Transparent);
|
||||
rec.SetCurrentValue(PureRectangle.BackgroundProperty, Brushes.Transparent);
|
||||
}
|
||||
if (canCloseOnClick)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user