wip
This commit is contained in:
@@ -9,7 +9,7 @@ public class AsyncHandlerInitialization<TMessage, TResponse, THandler>(IServiceP
|
|||||||
{
|
{
|
||||||
public void Initialize()
|
public void Initialize()
|
||||||
{
|
{
|
||||||
if (!StrongReferenceMessenger.Default.IsRegistered<ResponseEventArgs<TMessage, TResponse>>(provider))
|
if (!StrongReferenceMessenger.Default.IsRegistered<AsyncResponseEventArgs<TMessage, TResponse>>(provider))
|
||||||
{
|
{
|
||||||
StrongReferenceMessenger.Default.Register<IServiceProvider, AsyncResponseEventArgs<TMessage, TResponse>>(provider,
|
StrongReferenceMessenger.Default.Register<IServiceProvider, AsyncResponseEventArgs<TMessage, TResponse>>(provider,
|
||||||
(provider, args) =>
|
(provider, args) =>
|
||||||
@@ -29,7 +29,7 @@ public class AsyncHandlerInitialization<TMessage, THandler>(IServiceProvider pro
|
|||||||
{
|
{
|
||||||
public void Initialize()
|
public void Initialize()
|
||||||
{
|
{
|
||||||
if (!StrongReferenceMessenger.Default.IsRegistered<TMessage>(provider))
|
if (!StrongReferenceMessenger.Default.IsRegistered<AsyncResponseEventArgs<TMessage, Unit>>(provider))
|
||||||
{
|
{
|
||||||
StrongReferenceMessenger.Default.Register<IServiceProvider, AsyncResponseEventArgs<TMessage, Unit>>(provider,
|
StrongReferenceMessenger.Default.Register<IServiceProvider, AsyncResponseEventArgs<TMessage, Unit>>(provider,
|
||||||
(provider, args) =>
|
(provider, args) =>
|
||||||
|
|||||||
@@ -9,14 +9,15 @@ public class AsyncHandlerKeyedInitialization<TMessage, THandler>(string key, ISe
|
|||||||
{
|
{
|
||||||
public void Initialize()
|
public void Initialize()
|
||||||
{
|
{
|
||||||
if (!StrongReferenceMessenger.Default.IsRegistered<TMessage, string>(provider, key))
|
if (!StrongReferenceMessenger.Default.IsRegistered<AsyncResponseEventArgs<TMessage, Unit>, string>(provider, key))
|
||||||
{
|
{
|
||||||
StrongReferenceMessenger.Default.Register<IServiceProvider, TMessage, string>(provider, key,
|
StrongReferenceMessenger.Default.Register<IServiceProvider, AsyncResponseEventArgs<TMessage, Unit>, string>(provider, key,
|
||||||
(provider, args) =>
|
(provider, args) =>
|
||||||
{
|
{
|
||||||
foreach (IAsyncHandler<TMessage> handler in provider.GetKeyedServices<IAsyncHandler<TMessage>>(key))
|
foreach (IAsyncHandler<TMessage> handler in provider.GetKeyedServices<IAsyncHandler<TMessage>>(key))
|
||||||
{
|
{
|
||||||
handler.Handle(args);
|
handler.Handle(args.Message, args.CancellationToken);
|
||||||
|
args.Reply(Unit.Value);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -29,14 +30,14 @@ public class AsyncHandlerKeyedInitialization<TMessage, TResponse, THandler>(stri
|
|||||||
{
|
{
|
||||||
public void Initialize()
|
public void Initialize()
|
||||||
{
|
{
|
||||||
if (!StrongReferenceMessenger.Default.IsRegistered<ResponseEventArgs<TMessage, TResponse>, string>(provider, key))
|
if (!StrongReferenceMessenger.Default.IsRegistered<AsyncResponseEventArgs<TMessage, TResponse>, string>(provider, key))
|
||||||
{
|
{
|
||||||
StrongReferenceMessenger.Default.Register<IServiceProvider, ResponseEventArgs<TMessage, TResponse>, string>(provider, key,
|
StrongReferenceMessenger.Default.Register<IServiceProvider, AsyncResponseEventArgs<TMessage, TResponse>, string>(provider, key,
|
||||||
(provider, args) =>
|
(provider, args) =>
|
||||||
{
|
{
|
||||||
foreach (IAsyncHandler<TMessage, TResponse> handler in provider.GetKeyedServices<IAsyncHandler<TMessage, TResponse>>(key))
|
foreach (IAsyncHandler<TMessage, TResponse> handler in provider.GetKeyedServices<IAsyncHandler<TMessage, TResponse>>(key))
|
||||||
{
|
{
|
||||||
handler.Handle(args.Message);
|
args.Reply(handler.Handle(args.Message, args.CancellationToken));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace Toolkit.UI.Avalonia;
|
namespace Toolkit.Foundation;
|
||||||
|
|
||||||
public enum ForwardChaining
|
public enum ForwardChaining
|
||||||
{
|
{
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace Toolkit.UI.Avalonia;
|
namespace Toolkit.Foundation;
|
||||||
|
|
||||||
public interface ICondition
|
public interface ICondition
|
||||||
{
|
{
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
namespace Toolkit.Foundation;
|
||||||
|
|
||||||
|
public interface IDisposableApplication
|
||||||
|
{
|
||||||
|
void Dispose();
|
||||||
|
}
|
||||||
@@ -31,15 +31,31 @@ public static class IMessengerExtensions
|
|||||||
where TMessage : class, new() =>
|
where TMessage : class, new() =>
|
||||||
await messenger.Send(new AsyncResponseEventArgs<TMessage, TResponse> { Message = new TMessage() });
|
await messenger.Send(new AsyncResponseEventArgs<TMessage, TResponse> { Message = new TMessage() });
|
||||||
|
|
||||||
|
public static async Task<TResponse> SendAsync<TMessage, TResponse>(this IMessenger messenger,
|
||||||
|
string key) where TMessage : class, new() =>
|
||||||
|
await messenger.Send(new AsyncResponseEventArgs<TMessage, TResponse> { Message = new TMessage() }, key);
|
||||||
|
|
||||||
public static async Task<TResponse> SendAsync<TMessage, TResponse>(this IMessenger messenger,
|
public static async Task<TResponse> SendAsync<TMessage, TResponse>(this IMessenger messenger,
|
||||||
TMessage message) where TMessage : class =>
|
TMessage message) where TMessage : class =>
|
||||||
await messenger.Send(new AsyncResponseEventArgs<TMessage, TResponse> { Message = message });
|
await messenger.Send(new AsyncResponseEventArgs<TMessage, TResponse> { Message = message });
|
||||||
|
|
||||||
|
public static async Task<TResponse> SendAsync<TMessage, TResponse>(this IMessenger messenger,
|
||||||
|
TMessage message, string key) where TMessage : class =>
|
||||||
|
await messenger.Send(new AsyncResponseEventArgs<TMessage, TResponse> { Message = message }, key);
|
||||||
|
|
||||||
public static async Task SendAsync<TMessage>(this IMessenger messenger)
|
public static async Task SendAsync<TMessage>(this IMessenger messenger)
|
||||||
where TMessage : class, new() =>
|
where TMessage : class, new() =>
|
||||||
await messenger.Send(new AsyncResponseEventArgs<TMessage, Unit> { Message = new TMessage() });
|
await messenger.Send(new AsyncResponseEventArgs<TMessage, Unit> { Message = new TMessage() });
|
||||||
|
|
||||||
|
public static async Task SendAsync<TMessage>(this IMessenger messenger,
|
||||||
|
string key) where TMessage : class, new() =>
|
||||||
|
await messenger.Send(new AsyncResponseEventArgs<TMessage, Unit> { Message = new TMessage() }, key);
|
||||||
|
|
||||||
public static async Task SendAsync<TMessage>(this IMessenger messenger,
|
public static async Task SendAsync<TMessage>(this IMessenger messenger,
|
||||||
TMessage message) where TMessage : class =>
|
TMessage message) where TMessage : class =>
|
||||||
await messenger.Send(new AsyncResponseEventArgs<TMessage, Unit> { Message = message });
|
await messenger.Send(new AsyncResponseEventArgs<TMessage, Unit> { Message = message });
|
||||||
|
|
||||||
|
public static async Task SendAsync<TMessage>(this IMessenger messenger,
|
||||||
|
TMessage message, string key) where TMessage : class =>
|
||||||
|
await messenger.Send(new AsyncResponseEventArgs<TMessage, Unit> { Message = message }, key);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -486,9 +486,9 @@ public abstract partial class ObservableCollection<TViewModel> :
|
|||||||
protected override sealed void OnDeactivated()
|
protected override sealed void OnDeactivated()
|
||||||
{
|
{
|
||||||
Messenger.UnregisterAll(this);
|
Messenger.UnregisterAll(this);
|
||||||
Dispose();
|
|
||||||
|
|
||||||
Deactivated();
|
Deactivated();
|
||||||
|
|
||||||
|
Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void Activated()
|
protected virtual void Activated()
|
||||||
@@ -525,8 +525,6 @@ public abstract partial class ObservableCollection<TViewModel> :
|
|||||||
{
|
{
|
||||||
newSelection.IsSelected = true;
|
newSelection.IsSelected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Messenger.Send(Selection.As(SelectedItem));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SourceCollectionChanged(object? sender,
|
private void SourceCollectionChanged(object? sender,
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Xaml.Interactivity;
|
using Avalonia.Xaml.Interactivity;
|
||||||
|
using Toolkit.Foundation;
|
||||||
|
|
||||||
namespace Toolkit.UI.Avalonia;
|
namespace Toolkit.UI.Avalonia;
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Metadata;
|
using Avalonia.Metadata;
|
||||||
using Avalonia.Xaml.Interactivity;
|
using Avalonia.Xaml.Interactivity;
|
||||||
|
using Toolkit.Foundation;
|
||||||
|
|
||||||
namespace Toolkit.UI.Avalonia;
|
namespace Toolkit.UI.Avalonia;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Metadata;
|
using Avalonia.Metadata;
|
||||||
|
using Toolkit.Foundation;
|
||||||
|
|
||||||
namespace Toolkit.UI.Avalonia;
|
namespace Toolkit.UI.Avalonia;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
using Microsoft.UI.Xaml;
|
||||||
|
using Microsoft.Xaml.Interactions.Core;
|
||||||
|
using Toolkit.Foundation;
|
||||||
|
|
||||||
|
namespace Toolkit.UI.WinUI;
|
||||||
|
|
||||||
|
public class ComparisonCondition :
|
||||||
|
DependencyObject,
|
||||||
|
ICondition
|
||||||
|
{
|
||||||
|
public static readonly DependencyProperty LeftOperandProperty =
|
||||||
|
DependencyProperty.Register(nameof(LeftOperand),
|
||||||
|
typeof(object), typeof(ComparisonCondition),
|
||||||
|
new PropertyMetadata(null));
|
||||||
|
|
||||||
|
public static readonly DependencyProperty OperatorProperty =
|
||||||
|
DependencyProperty.Register(nameof(Operator),
|
||||||
|
typeof(ComparisonConditionType), typeof(ComparisonCondition),
|
||||||
|
new PropertyMetadata(null));
|
||||||
|
|
||||||
|
public static readonly DependencyProperty RightOperandProperty =
|
||||||
|
DependencyProperty.Register(nameof(RightOperand),
|
||||||
|
typeof(object), typeof(ComparisonCondition),
|
||||||
|
new PropertyMetadata(null));
|
||||||
|
|
||||||
|
public object LeftOperand
|
||||||
|
{
|
||||||
|
get => GetValue(LeftOperandProperty);
|
||||||
|
set => SetValue(LeftOperandProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public object RightOperand
|
||||||
|
{
|
||||||
|
get => GetValue(RightOperandProperty);
|
||||||
|
set => SetValue(RightOperandProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ComparisonConditionType Operator
|
||||||
|
{
|
||||||
|
get => (ComparisonConditionType)GetValue(OperatorProperty);
|
||||||
|
set => SetValue(OperatorProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Evaluate() =>
|
||||||
|
ComparisonLogic.Evaluate(LeftOperand, Operator, RightOperand);
|
||||||
|
}
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
using Microsoft.Xaml.Interactions.Core;
|
||||||
|
using System;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Globalization;
|
||||||
|
|
||||||
|
namespace Toolkit.UI.WinUI;
|
||||||
|
|
||||||
|
internal static class ComparisonLogic
|
||||||
|
{
|
||||||
|
internal static bool Evaluate(object leftOperand,
|
||||||
|
ComparisonConditionType operatorType,
|
||||||
|
object? rightOperand)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
|
||||||
|
if (leftOperand != null)
|
||||||
|
{
|
||||||
|
Type leftType = leftOperand.GetType();
|
||||||
|
|
||||||
|
if (rightOperand != null)
|
||||||
|
{
|
||||||
|
TypeConverter typeConverter = TypeDescriptor.GetConverter(leftType);
|
||||||
|
rightOperand = typeConverter.ConvertFrom(rightOperand);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (leftOperand is IComparable leftComparableOperand &&
|
||||||
|
rightOperand is IComparable rightComparableOperand)
|
||||||
|
{
|
||||||
|
return EvaluateComparable(leftComparableOperand, operatorType, rightComparableOperand);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (operatorType)
|
||||||
|
{
|
||||||
|
case ComparisonConditionType.Equal:
|
||||||
|
result = Equals(leftOperand, rightOperand);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ComparisonConditionType.NotEqual:
|
||||||
|
result = !Equals(leftOperand, rightOperand);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool EvaluateComparable(IComparable leftOperand,
|
||||||
|
ComparisonConditionType operatorType,
|
||||||
|
IComparable rightOperand)
|
||||||
|
{
|
||||||
|
object? convertedOperand = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
convertedOperand = Convert.ChangeType(rightOperand, leftOperand.GetType(), CultureInfo.CurrentCulture);
|
||||||
|
}
|
||||||
|
catch (FormatException)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
catch (InvalidCastException)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
if (convertedOperand == null)
|
||||||
|
{
|
||||||
|
return operatorType == ComparisonConditionType.NotEqual;
|
||||||
|
}
|
||||||
|
|
||||||
|
int comparison = leftOperand.CompareTo((IComparable)convertedOperand);
|
||||||
|
bool result = false;
|
||||||
|
|
||||||
|
switch (operatorType)
|
||||||
|
{
|
||||||
|
case ComparisonConditionType.Equal:
|
||||||
|
result = comparison == 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ComparisonConditionType.GreaterThan:
|
||||||
|
result = comparison > 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ComparisonConditionType.GreaterThanOrEqual:
|
||||||
|
result = comparison >= 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ComparisonConditionType.LessThan:
|
||||||
|
result = comparison < 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ComparisonConditionType.LessThanOrEqual:
|
||||||
|
result = comparison <= 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ComparisonConditionType.NotEqual:
|
||||||
|
result = comparison != 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
using Microsoft.UI.Xaml;
|
||||||
|
using Microsoft.UI.Xaml.Markup;
|
||||||
|
using Microsoft.Xaml.Interactivity;
|
||||||
|
using Toolkit.Foundation;
|
||||||
|
|
||||||
|
namespace Toolkit.UI.WinUI;
|
||||||
|
|
||||||
|
[ContentProperty(Name = nameof(Actions))]
|
||||||
|
public class ConditionAction :
|
||||||
|
DependencyObject,
|
||||||
|
IAction
|
||||||
|
{
|
||||||
|
public static readonly DependencyProperty ActionsProperty =
|
||||||
|
DependencyProperty.Register(nameof(Actions),
|
||||||
|
typeof(ActionCollection), typeof(ConditionAction),
|
||||||
|
new PropertyMetadata(null));
|
||||||
|
|
||||||
|
public static readonly DependencyProperty ConditionProperty =
|
||||||
|
DependencyProperty.Register(nameof(Condition),
|
||||||
|
typeof(ICondition), typeof(ConditionAction),
|
||||||
|
new PropertyMetadata(null));
|
||||||
|
|
||||||
|
private ActionCollection? actions;
|
||||||
|
|
||||||
|
public ActionCollection Actions => actions ??= [];
|
||||||
|
|
||||||
|
public ICondition? Condition
|
||||||
|
{
|
||||||
|
get => (ICondition?)GetValue(ConditionProperty);
|
||||||
|
set => SetValue(ConditionProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public object? Execute(object? sender, object? parameter)
|
||||||
|
{
|
||||||
|
if (Condition?.Evaluate() == true)
|
||||||
|
{
|
||||||
|
Interaction.ExecuteActions(sender, Actions, parameter);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
using System.Collections.ObjectModel;
|
||||||
|
|
||||||
|
namespace Toolkit.UI.WinUI;
|
||||||
|
|
||||||
|
public class ConditionCollection :
|
||||||
|
ObservableCollection<ComparisonCondition>
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
using Microsoft.UI.Xaml;
|
||||||
|
using Microsoft.UI.Xaml.Markup;
|
||||||
|
using Toolkit.Foundation;
|
||||||
|
|
||||||
|
namespace Toolkit.UI.WinUI;
|
||||||
|
|
||||||
|
[ContentProperty(Name = nameof(Conditions))]
|
||||||
|
public class ConditionalExpression :
|
||||||
|
DependencyObject,
|
||||||
|
ICondition
|
||||||
|
{
|
||||||
|
public static readonly DependencyProperty ConditionsProperty =
|
||||||
|
DependencyProperty.Register(nameof(Conditions),
|
||||||
|
typeof(ConditionCollection), typeof(ConditionalExpression),
|
||||||
|
new PropertyMetadata(new ConditionCollection()));
|
||||||
|
|
||||||
|
public static readonly DependencyProperty ForwardChainingProperty =
|
||||||
|
DependencyProperty.Register(nameof(ForwardChaining),
|
||||||
|
typeof(ForwardChaining), typeof(ConditionalExpression),
|
||||||
|
new PropertyMetadata(ForwardChaining.And));
|
||||||
|
|
||||||
|
public ConditionalExpression()
|
||||||
|
{
|
||||||
|
SetValue(ConditionsProperty, new ConditionCollection());
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConditionCollection Conditions =>
|
||||||
|
(ConditionCollection)GetValue(ConditionsProperty);
|
||||||
|
|
||||||
|
public ForwardChaining ForwardChaining
|
||||||
|
{
|
||||||
|
get => (ForwardChaining)GetValue(ForwardChainingProperty);
|
||||||
|
set => SetValue(ForwardChainingProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Evaluate()
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
foreach (var operation in Conditions)
|
||||||
|
{
|
||||||
|
result = operation.Evaluate();
|
||||||
|
|
||||||
|
if (!result && ForwardChaining == ForwardChaining.And)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result && ForwardChaining == ForwardChaining.Or)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,7 +3,8 @@ using System.Diagnostics.CodeAnalysis;
|
|||||||
|
|
||||||
namespace Toolkit.WinUI;
|
namespace Toolkit.WinUI;
|
||||||
|
|
||||||
public interface IWindowRegistry
|
public interface IWindowRegistry :
|
||||||
|
IDisposable
|
||||||
{
|
{
|
||||||
void Add(Window window);
|
void Add(Window window);
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
using Microsoft.UI.Xaml;
|
using Microsoft.UI.Xaml;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using System.Reactive.Disposables;
|
||||||
|
using Toolkit.Foundation;
|
||||||
|
|
||||||
namespace Toolkit.WinUI;
|
namespace Toolkit.WinUI;
|
||||||
|
|
||||||
public class WindowRegistry :
|
public class WindowRegistry(IDisposer disposer) :
|
||||||
IWindowRegistry
|
IWindowRegistry
|
||||||
{
|
{
|
||||||
private readonly List<Window> windows = [];
|
private readonly List<Window> windows = [];
|
||||||
@@ -19,13 +21,27 @@ public class WindowRegistry :
|
|||||||
}
|
}
|
||||||
|
|
||||||
windows.Add(window);
|
windows.Add(window);
|
||||||
|
|
||||||
|
disposer.Add(this, Disposable.Create(() =>
|
||||||
|
{
|
||||||
|
windows.Remove(window);
|
||||||
|
window.Close();
|
||||||
|
}));
|
||||||
|
|
||||||
window.Closed += OnWindowClosed;
|
window.Closed += OnWindowClosed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
disposer.Dispose(this);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
public bool TryGet<TWindow>([DisallowNull] out TWindow? window)
|
public bool TryGet<TWindow>([DisallowNull] out TWindow? window)
|
||||||
where TWindow : Window
|
where TWindow : Window
|
||||||
{
|
{
|
||||||
|
|
||||||
window = windows.OfType<TWindow>().FirstOrDefault() ?? null;
|
window = windows.OfType<TWindow>().FirstOrDefault() ?? null;
|
||||||
return window is not null;
|
return window is not null;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user