依赖项:
1.UI-Uras ;
2.Prism.Avalonia;
3.Ursa.PrismExtension
解决思路:
重新注入IDialogService
实现代码(大部分是Prism的源码):
public class UrsaExtDialogService : IDialogService
{
private readonly IContainerExtension _containerExtension;
/// <summary>Initializes a new instance of the <see cref="DialogService"/> class.</summary>
/// <param name="containerExtension">The <see cref="IContainerExtension" /></param>
public UrsaExtDialogService(IContainerExtension containerExtension)
{
_containerExtension = containerExtension;
}
public void ShowDialog(string name, IDialogParameters parameters, DialogCallback callback)
{
parameters ??= new DialogParameters();
var isModal = parameters.TryGetValue<bool>(
KnownDialogParameters.ShowNonModal,
out var show
)
? !show
: true;
var windowName = parameters.TryGetValue<string>(
KnownDialogParameters.WindowName,
out var wName
)
? wName
: null;
var owner = parameters.TryGetValue<Window>(
KnownDialogParameters.ParentWindow,
out var hWnd
)
? hWnd
: null;
IDialogWindow dialogWindow = CreateDialogWindow(windowName);
ConfigureDialogWindowEvents(dialogWindow, callback);
ConfigureDialogWindowContent(name, dialogWindow, parameters);
ShowDialogWindow(dialogWindow, isModal, owner);
}
private void ShowUras()
{
var control = new DefaultDialogControl();
//control.Content =
}
protected virtual void ShowDialogWindow(
IDialogWindow dialogWindow,
bool isModal,
Window owner = null
)
{
if (
isModal
&& Application.Current?.ApplicationLifetime
is IClassicDesktopStyleApplicationLifetime deskLifetime
)
{
if (owner != null)
dialogWindow.ShowDialog(owner);
else
dialogWindow.ShowDialog(deskLifetime.MainWindow);
}
else
{
dialogWindow.Show();
}
}
protected virtual IDialogWindow CreateDialogWindow(string name)
{
if (string.IsNullOrWhiteSpace(name))
return _containerExtension.Resolve<IDialogWindow>();
else
return _containerExtension.Resolve<IDialogWindow>(name);
}
protected void ConfigureDialogWindowContent(
string dialogName,
IDialogWindow window,
IDialogParameters parameters
)
{
var content = _containerExtension.Resolve<object>(dialogName);
if (!(content is Avalonia.Controls.Control dialogContent))
throw new NullReferenceException("A dialog's content must be a FrameworkElement");
MvvmHelpers.AutowireViewModel(dialogContent);
if (!(dialogContent.DataContext is IDialogAware viewModel))
throw new NullReferenceException(
"A dialog's ViewModel must implement the IDialogAware interface"
);
ConfigureDialogWindowProperties(window, dialogContent, viewModel);
MvvmHelpers.ViewAndViewModelAction<IDialogAware>(
viewModel,
d => d.OnDialogOpened(parameters)
);
}
protected virtual void ConfigureDialogWindowEvents(
IDialogWindow dialogWindow,
DialogCallback callback
)
{
Action<IDialogResult> requestCloseHandler = (result) =>
{
dialogWindow.Result = result;
dialogWindow.Close();
};
EventHandler loadedHandler = null;
loadedHandler = (o, e) =>
{
dialogWindow.Opened -= loadedHandler;
DialogUtilities.InitializeListener(
dialogWindow.DataContext as IDialogAware,
requestCloseHandler
);
};
dialogWindow.Opened += loadedHandler;
EventHandler<WindowClosingEventArgs> closingHandler = null;
closingHandler = (o, e) =>
{
if (!(dialogWindow.DataContext as IDialogAware).CanCloseDialog())
e.Cancel = true;
};
dialogWindow.Closing += closingHandler;
EventHandler closedHandler = null;
closedHandler = async (o, e) =>
{
dialogWindow.Closed -= closedHandler;
dialogWindow.Closing -= closingHandler;
(dialogWindow.DataContext as IDialogAware).OnDialogClosed();
if (dialogWindow.Result == null)
dialogWindow.Result = new Prism.Dialogs.DialogResult();
await callback.Invoke(dialogWindow.Result);
dialogWindow.DataContext = null;
dialogWindow.Content = null;
};
dialogWindow.Closed += closedHandler;
}
protected virtual void ConfigureDialogWindowProperties(
IDialogWindow window,
Avalonia.Controls.Control dialogContent,
IDialogAware viewModel
)
{
window.Content = dialogContent;
window.DataContext = viewModel;
}
}
实现IDialogWindow
public class PrismDialogControl : DefaultDialogControl, IDialogWindow
{
public PrismDialogControl() { }
protected override void OnElementClosing(object? sender, object? args)
{
base.OnElementClosing(sender, args);
Closing?.Invoke(sender, args as WindowClosingEventArgs);
}
protected override void OnLoaded(RoutedEventArgs e)
{
base.OnLoaded(e);
Opened?.Invoke(this, e as System.EventArgs);
}
public override void Close()
{
base.Close();
Closed?.Invoke(this, new System.EventArgs());
}
public WindowBase Owner { get; set; }
public IDialogResult Result { get; set; }
public event EventHandler Opened;
public event EventHandler<WindowClosingEventArgs>? Closing;
new public event EventHandler Closed;
public void Show()
{
OverlayDialog.ShowCustom(
this,
this.DataContext,
null,
new OverlayDialogOptions() { IsCloseButtonVisible = false }
);
}
public Task ShowDialog(Window owner)
{
return OverlayDialog.ShowCustomModal<IDialogResult>(
this,
this.DataContext,
null,
new OverlayDialogOptions() { IsCloseButtonVisible = false }
);
}
}