Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DialogService Host Window #76

Merged
merged 1 commit into from
Jun 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
161 changes: 89 additions & 72 deletions samples/SampleDialogApp/ViewModels/DialogViewModel.cs
Original file line number Diff line number Diff line change
@@ -1,81 +1,98 @@
using System;
using Avalonia.Controls;
using Prism.Commands;
using Prism.Mvvm;
using Prism.Regions;
using Prism.Services.Dialogs;
using SampleDialogApp.Views;

namespace SampleDialogApp.ViewModels
namespace SampleDialogApp.ViewModels;

public class DialogViewModel : BindableBase, IDialogAware
{
public class DialogViewModel : BindableBase, IDialogAware
private readonly IDialogService _dialogService;
private string _customMessage = string.Empty;
private string _title = "Notification";
private Window? _parentWindow = null;

public DialogViewModel(IDialogService dialogService)
{
_dialogService = dialogService;

// This is a ViewModel of a pop-up dialog,
// the Title is pre-binded to Prism.Avalonia's DialogService
Title = "I'm a Sample Dialog!";
}

public string Title
{
get => _title;
set => SetProperty(ref _title, value);
}

/// <summary>Gets or sets the optional parent window of this Dialog pop-up.</summary>
public Window? ParentWindow
{
get => _parentWindow;
set => SetProperty(ref _parentWindow, value);
}

public DelegateCommand CmdModalDialog => new(() =>
{
var title = "MessageBox Title Here";
var message = "Hello, I am a modal MessageBox window.\n\n" +
$"I {(ParentWindow == null ? "dont" : "do")} have a parent.";

_dialogService.ShowDialog(
ParentWindow,
nameof(MessageBoxView),
new DialogParameters($"title={title}&message={message}"),
r => { });
});

public DelegateCommand<string> CmdResult => new DelegateCommand<string>((param) =>
{
// None = 0
// OK = 1
// Cancel = 2
// Abort = 3
// Retry = 4
// Ignore = 5
// Yes = 6
// No = 7
ButtonResult result = ButtonResult.None;

if (int.TryParse(param, out int intResult))
result = (ButtonResult)intResult;

RaiseRequestClose(new DialogResult(result));
});

public string CustomMessage
{
get => _customMessage;
set => SetProperty(ref _customMessage, value);
}

public event Action<IDialogResult>? RequestClose;

public virtual bool CanCloseDialog()
{
// Allow the dialog to close
return true;
}

public virtual void OnDialogClosed()
{
System.Diagnostics.Debug.WriteLine("Detach custom event handlers here, etc.");
}

public void OnDialogOpened(IDialogParameters parameters)
{
CustomMessage = parameters.GetValue<string>("message");
}

public virtual void RaiseRequestClose(IDialogResult dialogResult)
{
private readonly IDialogService _dialog;
private string _customMessage;
private string _title = "Notification";

public DialogViewModel()
{
// Since this is a basic ShellWindow, there's nothing
// to do here.
// For enterprise apps, you could register up subscriptions
// or other startup background tasks so that they get triggered
// on startup, rather than putting them in the DashboardViewModel.
//
// For example, initiate the pulling of News Feeds, etc.

Title = "Sample Dialog!";
}

public string Title
{
get => _title;
set => SetProperty(ref _title, value);
}

public DelegateCommand<string> CmdResult => new DelegateCommand<string>((param) =>
{
// None = 0
// OK = 1
// Cancel = 2
// Abort = 3
// Retry = 4
// Ignore = 5
// Yes = 6
// No = 7
ButtonResult result = ButtonResult.None;

if (int.TryParse(param, out int intResult))
result = (ButtonResult)intResult;

RaiseRequestClose(new DialogResult(result));
});

public string CustomMessage
{
get => _customMessage;
set => SetProperty(ref _customMessage, value);
}

public event Action<IDialogResult> RequestClose;

public virtual bool CanCloseDialog()
{
// Allow the dialog to close
return true;
}

public virtual void OnDialogClosed()
{
// Detatch custom eventhandlers here, etc.
}

public void OnDialogOpened(IDialogParameters parameters)
{
CustomMessage = parameters.GetValue<string>("message");
}

public virtual void RaiseRequestClose(IDialogResult dialogResult)
{
RequestClose?.Invoke(dialogResult);
}
RequestClose?.Invoke(dialogResult);
}
}
1 change: 0 additions & 1 deletion samples/SampleDialogApp/ViewModels/MessageBoxViewModel.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using System;
using Prism.Commands;
using Prism.Mvvm;
using Prism.Regions;
using Prism.Services.Dialogs;

namespace SampleDialogApp.ViewModels;
Expand Down
43 changes: 27 additions & 16 deletions samples/SampleDialogApp/Views/DialogView.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,37 @@
Height="200" Width="400"
x:Class="SampleDialogApp.Views.DialogView">
<StackPanel HorizontalAlignment="Center" Spacing=" 5">
<Label Content="{Binding Title}" FontWeight="Bold" />
<!--<Label Content="{Binding Title}" FontWeight="Bold" />-->

<Label Content="Show Modal Dialog:" />
<StackPanel Orientation="Horizontal" Spacing="5">
<Button Content="Modal from .AXAML.CS" Click="BtnShowModal_Click" />
<Button Content="Modal from MVVM" Command="{Binding CmdModalDialog}" />
</StackPanel>

<StackPanel Orientation="Horizontal">
<Label Content="Custom Param:" />
<Label Content="{Binding CustomMessage}" />
</StackPanel>

<StackPanel Orientation="Horizontal" Spacing="5">
<Button Content="None" Command="{Binding CmdResult}" CommandParameter="0" />
<Button Content="OK" Command="{Binding CmdResult}" CommandParameter="1" />
<Button Content="Cancel" Command="{Binding CmdResult}" CommandParameter="2" />
</StackPanel>
<StackPanel Orientation="Horizontal" Spacing="5">
<Button Content="Abort" Command="{Binding CmdResult}" CommandParameter="3" />
<Button Content="Retry" Command="{Binding CmdResult}" CommandParameter="4" />
<Button Content="Ignore" Command="{Binding CmdResult}" CommandParameter="5" />
</StackPanel>
<StackPanel Orientation="Horizontal" Spacing="5">
<Button Content="Yes" Command="{Binding CmdResult}" CommandParameter="6" />
<Button Content="No" Command="{Binding CmdResult}" CommandParameter="7" />
</StackPanel>
<Grid RowDefinitions="auto,auto,auto" ColumnDefinitions="auto,auto,auto">
<Grid.Styles>
<Style Selector="Button">
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="Margin" Value="2" />
</Style>
</Grid.Styles>

<Button Grid.Row="0" Grid.Column="0" Content="None" Command="{Binding CmdResult}" CommandParameter="0" />
<Button Grid.Row="0" Grid.Column="1" Content="OK" Command="{Binding CmdResult}" CommandParameter="1" />
<Button Grid.Row="0" Grid.Column="2" Content="Cancel" Command="{Binding CmdResult}" CommandParameter="2" />

<Button Grid.Row="1" Grid.Column="0" Content="Abort" Command="{Binding CmdResult}" CommandParameter="3" />
<Button Grid.Row="1" Grid.Column="1" Content="Retry" Command="{Binding CmdResult}" CommandParameter="4" />
<Button Grid.Row="1" Grid.Column="2" Content="Ignore" Command="{Binding CmdResult}" CommandParameter="5" />

<Button Grid.Row="2" Grid.Column="0" Content="Yes" Command="{Binding CmdResult}" CommandParameter="6" />
<Button Grid.Row="2" Grid.Column="1" Content="No" Command="{Binding CmdResult}" CommandParameter="7" />
</Grid>
</StackPanel>
</UserControl>
</UserControl>
48 changes: 40 additions & 8 deletions samples/SampleDialogApp/Views/DialogView.axaml.cs
Original file line number Diff line number Diff line change
@@ -1,18 +1,50 @@
using Avalonia.Controls;
using Avalonia.Interactivity;
using Avalonia.Markup.Xaml;
using Prism.Ioc;
using Prism.Services.Dialogs;
using SampleDialogApp.ViewModels;

namespace SampleDialogApp.Views
namespace SampleDialogApp.Views;

public partial class DialogView : UserControl
{
public partial class DialogView : UserControl
public DialogView()
{
InitializeComponent();
}

protected override void OnInitialized()
{
public DialogView()
base.OnInitialized();

// Pass the parent window to the ViewModel
// given that the ViewModel has been binded to this view
DialogViewModel? viewModel = this.DataContext as DialogViewModel;
if (this.Parent is Window parent &&
viewModel is not null)
{
InitializeComponent();
viewModel.ParentWindow = parent;
}
}

private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}

private void BtnShowModal_Click(object sender, RoutedEventArgs args)
{
var dialogSvc = ContainerLocator.Current.Resolve<IDialogService>();

var title = "MessageBox Title Here";
var message = "Hello, I am a simple modal MessageBox with an OK button.\n\n" +
"I've been called by the `.axaml.cs` UserControl.";

////private void InitializeComponent()
////{
//// AvaloniaXamlLoader.Load(this);
////}
dialogSvc.ShowDialog(
this.Parent as Window,
nameof(MessageBoxView),
new DialogParameters($"title={title}&message={message}"),
r => { });
}
}
26 changes: 20 additions & 6 deletions src/Prism.Avalonia/Services/Dialogs/DialogService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,13 @@ public void ShowDialog(string name, IDialogParameters parameters, Action<IDialog
ShowDialogInternal(name, parameters, callback, true, windowName);
}

void ShowDialogInternal(string name, IDialogParameters parameters, Action<IDialogResult> callback, bool isModal, string windowName = null)
/// <inheritdoc/>
public void ShowDialog(Window owner, string name, IDialogParameters parameters, Action<IDialogResult> callback)
{
ShowDialogInternal(name, parameters, callback, true, parentWindow: owner);
}

private void ShowDialogInternal(string name, IDialogParameters parameters, Action<IDialogResult> callback, bool isModal, string windowName = null, Window parentWindow = null)
{
if (parameters == null)
parameters = new DialogParameters();
Expand All @@ -84,24 +90,29 @@ void ShowDialogInternal(string name, IDialogParameters parameters, Action<IDialo
ConfigureDialogWindowEvents(dialogWindow, callback);
ConfigureDialogWindowContent(name, dialogWindow, parameters);

ShowDialogWindow(dialogWindow, isModal);
ShowDialogWindow(dialogWindow, isModal, parentWindow);
}

/// <summary>
/// Shows the dialog window.
/// </summary>
/// <param name="dialogWindow">The dialog window to show.</param>
/// <param name="isModal">If true; dialog is shown as a modal</param>
protected virtual void ShowDialogWindow(IDialogWindow dialogWindow, bool isModal)
/// <param name="owner">Optional host window of the dialog.</param>
protected virtual void ShowDialogWindow(IDialogWindow dialogWindow, bool isModal, Window owner = null)
{
if (isModal &&
if (isModal &&
Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime deskLifetime)
{
// Ref:
// - https://docs.avaloniaui.net/docs/controls/window#show-a-window-as-a-dialog
// - https://github.com/AvaloniaUI/Avalonia/discussions/7924
// (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktopLifetime)
dialogWindow.ShowDialog(deskLifetime.MainWindow);

if (owner != null)
dialogWindow.ShowDialog(owner);
else
dialogWindow.ShowDialog(deskLifetime.MainWindow);
}
else
{
Expand Down Expand Up @@ -149,7 +160,7 @@ protected virtual void ConfigureDialogWindowContent(string dialogName, IDialogWi
/// </summary>
/// <param name="dialogWindow">The hosting window.</param>
/// <param name="callback">The action to perform when the dialog is closed.</param>
protected virtual void ConfigureDialogWindowEvents(IDialogWindow dialogWindow, Action<IDialogResult> callback)
protected virtual void ConfigureDialogWindowEvents(IDialogWindow dialogWindow, Action<IDialogResult>? callback)
{
Action<IDialogResult> requestCloseHandler = null;
requestCloseHandler = (o) =>
Expand All @@ -167,6 +178,7 @@ protected virtual void ConfigureDialogWindowEvents(IDialogWindow dialogWindow, A
dialogWindow.Opened -= loadedHandler;
dialogWindow.GetDialogViewModel().RequestClose += requestCloseHandler;
};

dialogWindow.Opened += loadedHandler;
//// WPF: dialogWindow.Loaded += loadedHandler;

Expand All @@ -176,6 +188,7 @@ protected virtual void ConfigureDialogWindowEvents(IDialogWindow dialogWindow, A
if (!dialogWindow.GetDialogViewModel().CanCloseDialog())
e.Cancel = true;
};

dialogWindow.Closing += closingHandler;

EventHandler closedHandler = null;
Expand All @@ -195,6 +208,7 @@ protected virtual void ConfigureDialogWindowEvents(IDialogWindow dialogWindow, A
dialogWindow.DataContext = null;
dialogWindow.Content = null;
};

dialogWindow.Closed += closedHandler;
}

Expand Down
Loading