simplify things a bit more
MODIFY
WalletWasabi.Fluent/Controls/DialogContentHost.cs
WalletWasabi.Fluent/Controls/DialogContentHost.cs
using System;
+using System.Windows.Input;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Primitives;
+using ReactiveUI;
using WalletWasabi.Fluent.ViewModels.Dialog;
namespace WalletWasabi.Fluent.Controls
{
/// <summary>
- /// Manages and hosts dialogs when it's bound to <see cref="IDialogHost"/> objects.
+ /// Manages and hosts dialogs when it's bound to <see cref="IContent"/> objects.
/// </summary>
public class DialogContentHost : TemplatedControl
{
- public static readonly StyledProperty<IDialogHost> DialogHostProperty =
- AvaloniaProperty.Register<DialogContentHost, IDialogHost>(nameof(DialogHost));
+ public static readonly StyledProperty<DialogViewModelBase> ContentProperty =
+ AvaloniaProperty.Register<DialogContentHost, DialogViewModelBase>(nameof(Content));
+
+ public static readonly StyledProperty<ICommand> CloseDialogCommandProperty =
+ AvaloniaProperty.Register<DialogContentHost, ICommand>(nameof(CloseDialogCommand));
static DialogContentHost()
{
- DialogHostProperty.Changed.AddClassHandler<DialogContentHost>(OnDialogHostPropertyChanged);
+ ContentProperty.Changed.AddClassHandler<DialogContentHost>(OnContentPropertyChanged);
}
- /// <summary>
- /// Gets or sets the VM that implements <see cref="IDialogHost"/>
- /// </summary>
- public IDialogHost DialogHost
+ public DialogContentHost()
{
- get => GetValue(DialogHostProperty);
- set => SetValue(DialogHostProperty, value);
+ CloseDialogCommand = ReactiveCommand.Create(() => Content.IsDialogOpen = false);
}
- private static void OnDialogHostPropertyChanged(DialogContentHost arg1, AvaloniaPropertyChangedEventArgs arg2)
+ private static void OnContentPropertyChanged(DialogContentHost arg1, AvaloniaPropertyChangedEventArgs arg2)
{
- (arg2.NewValue as IDialogHost)?.SetDialogStateListener(x =>
+ (arg2.NewValue as DialogViewModelBase)?.WhenAnyValue(x => x.IsDialogOpen).Subscribe(x =>
{
arg1.PseudoClasses.Set(":open", x);
});
}
+ /// <summary>
+ /// Gets or sets the VM that implements <see cref="IContent"/>
+ /// </summary>
+ public DialogViewModelBase Content
+ {
+ get => GetValue(ContentProperty);
+ set => SetValue(ContentProperty, value);
+ }
+
+ public ICommand CloseDialogCommand
+ {
+ get => GetValue(CloseDialogCommandProperty);
+ set => SetValue(CloseDialogCommandProperty, value);
+ }
+
public void CloseDialog()
{
- DialogHost?.CloseDialog();
+ Content.IsDialogOpen = false;
}
}
}

MODIFY
WalletWasabi.Fluent/Controls/DialogContentHost.xaml
WalletWasabi.Fluent/Controls/DialogContentHost.xaml
<ControlTemplate>
<Panel>
<Panel Background="#272727" Name="PART_Overlay">
- <Button Classes="invisible" Command="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=CloseDialog}"/>
+ <Button Classes="invisible" Command="{TemplateBinding CloseDialogCommand}"/>
</Panel>
<Panel Name="PART_DialogHost" VerticalAlignment="Center" HorizontalAlignment="Center">
<Border CornerRadius="5" BoxShadow="4 11 30 1 #90000000" Background="#323232" >
- <ContentPresenter Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=DialogHost.CurrentDialog}"/>
+ <ContentPresenter Content="{TemplateBinding Content}"/>
</Border>
</Panel>
</Panel>

MODIFY
WalletWasabi.Fluent/ViewModels/Dialog/DialogViewModelBaseOfTResult.cs
WalletWasabi.Fluent/ViewModels/Dialog/DialogViewModelBaseOfTResult.cs
@@ -9,9 +9,6 @@ namespace WalletWasabi.Fluent.ViewModels.Dialog
/// <typeparam name="TResult">The type of the value to be returned when the dialog is finished.</typeparam>
public abstract class DialogViewModelBase<TResult> : DialogViewModelBase
{
- public DialogViewModelBase(IDialogHost dialogViewModel) : base(dialogViewModel)
- {
- }
private TaskCompletionSource<TResult> CurrentTaskCompletionSource { get; set; }
@@ -22,17 +19,25 @@ namespace WalletWasabi.Fluent.ViewModels.Dialog
/// <param name="value">The return value of the dialog</param>
public void CloseDialog(TResult value)
{
+ if (IsDialogOpen is false)
+ {
+ throw new InvalidOperationException("Dialog was already closed.");
+ }
+
CurrentTaskCompletionSource.SetResult(value);
CurrentTaskCompletionSource = null;
- DialogHost.CloseDialog();
+
+ IsDialogOpen = false;
}
/// <summary>
/// Shows the dialog.
/// </summary>
/// <returns>The value to be returned when the dialog is finished.</returns>
- public Task<TResult> ShowDialogAsync()
+ public Task<TResult> ShowDialogAsync(IDialogHost host)
{
+ host.CurrentDialog = this;
+
if (CurrentTaskCompletionSource is { })
{
throw new InvalidOperationException("Can't open a new dialog since there's already one active.");
@@ -40,7 +45,7 @@ namespace WalletWasabi.Fluent.ViewModels.Dialog
CurrentTaskCompletionSource = new TaskCompletionSource<TResult>();
- DialogHost.ShowDialog(this);
+ IsDialogOpen = true;
DialogShown();
return CurrentTaskCompletionSource.Task;

MODIFY
WalletWasabi.Fluent/ViewModels/Dialog/IDialogHost.cs
WalletWasabi.Fluent/ViewModels/Dialog/IDialogHost.cs
@@ -13,18 +13,5 @@ namespace WalletWasabi.Fluent.ViewModels.Dialog
/// The currently active dialog. The modal dialog UI should close when this is null.
/// </summary>
DialogViewModelBase? CurrentDialog { get; set; }
-
- /// <summary>
- /// Close the currently displayed dialog.
- /// </summary>
- void CloseDialog();
-
- /// <summary>
- /// Show a dialog from a ViewModel with <see cref="DialogViewModelBase{TResult}"/> as its base.
- /// </summary>
- /// <param name="dialogViewModel">The instance of the Dialog ViewModel to be displayed</param>
- void ShowDialog<TDialog>(TDialog dialogViewModel) where TDialog : DialogViewModelBase;
-
- void SetDialogStateListener(Action<bool> listener);
}
}
\ No newline at end of file

MODIFY
WalletWasabi.Fluent/ViewModels/MainViewModel.cs
WalletWasabi.Fluent/ViewModels/MainViewModel.cs
@@ -16,7 +16,6 @@ namespace WalletWasabi.Fluent.ViewModels
private string _title = "Wasabi Wallet";
private DialogViewModelBase? _currentDialog;
private NavBarViewModel _navBar;
- private bool _isDialogOpen;
public MainViewModel(Global global)
{
_global = global;
@@ -64,12 +63,6 @@ namespace WalletWasabi.Fluent.ViewModels
internal set => this.RaiseAndSetIfChanged(ref _title, value);
}
- public bool IsDialogOpen
- {
- get => _isDialogOpen;
- set => this.RaiseAndSetIfChanged(ref _isDialogOpen, value);
- }
-
public void Initialize()
{
// Temporary to keep things running without VM modifications.
@@ -83,21 +76,21 @@ namespace WalletWasabi.Fluent.ViewModels
}
}
- void IDialogHost.ShowDialog<TDialog>(TDialog dialogViewModel)
- {
- var dialogHost = (this as IDialogHost);
- dialogHost.CurrentDialog = dialogViewModel;
- DialogStateListener(true);
- }
-
- void IDialogHost.CloseDialog()
- {
- DialogStateListener(false);
- }
-
- public void SetDialogStateListener(Action<bool> listener)
- {
- this.DialogStateListener = listener;
- }
+ // void IDialogHost.ShowDialog<TDialog>(TDialog dialogViewModel)
+ // {
+ // var dialogHost = (this as IDialogHost);
+ // dialogHost.CurrentDialog = dialogViewModel;
+ // DialogStateListener(true);
+ // }
+
+ // void IDialogHost.CloseDialog()
+ // {
+ // DialogStateListener(false);
+ // }
+
+ // public void SetDialogStateListener(Action<bool> listener)
+ // {
+ // this.DialogStateListener = listener;
+ // }
}
}

MODIFY
WalletWasabi.Fluent/ViewModels/SettingsPageViewModel.cs
WalletWasabi.Fluent/ViewModels/SettingsPageViewModel.cs
@@ -13,8 +13,8 @@ namespace WalletWasabi.Fluent.ViewModels
OpenDialogCommand = ReactiveCommand.Create(async () =>
{
- var x = new TestDialogViewModel(MainViewModel.Instance);
- var result = await x.ShowDialogAsync();
+ var x = new TestDialogViewModel();
+ var result = await x.ShowDialogAsync(MainViewModel.Instance);
});
}

MODIFY
WalletWasabi.Fluent/ViewModels/TestDialogViewModel.cs
WalletWasabi.Fluent/ViewModels/TestDialogViewModel.cs
@@ -6,10 +6,6 @@ namespace WalletWasabi.Fluent.ViewModels
{
public class TestDialogViewModel : DialogViewModelBase<string>
{
- public TestDialogViewModel(IDialogHost dialogViewModel) : base(dialogViewModel)
- {
- }
-
protected override void DialogShown()
{
}

MODIFY
WalletWasabi.Fluent/Views/MainWindow.axaml
WalletWasabi.Fluent/Views/MainWindow.axaml
<Panel Margin="{Binding #MainWindow.OffScreenMargin}">
<local:MainView />
- <c:DialogContentHost DialogHost="{Binding .}"/>
+ <c:DialogContentHost Content="{Binding CurrentDialog}"/>
</Panel>
</Window>

simplify things a bit more