Skip to content

OnUIThread-Refactor and a few improvements #963

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

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
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
6 changes: 2 additions & 4 deletions src/Caliburn.Micro.Avalonia.Tests/ScopeNamingRouteTests.cs
Original file line number Diff line number Diff line change
@@ -25,8 +25,7 @@ public void CorrectlyGetsAddedHop()
var d1 = new AvaloniaObject();
var d2 = new AvaloniaObject();
route.AddHop(d1, d2);
AvaloniaObject target;
var result = route.TryGetHop(d1, out target);
var result = route.TryGetHop(d1, out AvaloniaObject target);
Assert.True(result);
Assert.Same(d2, target);
}
@@ -52,9 +51,8 @@ public void GetsAllHopsAdded()
};

var source = d1;
AvaloniaObject target;

while (route.TryGetHop(source, out target))
while (route.TryGetHop(source, out AvaloniaObject target))
{
all.Remove(target);
source = target;
2 changes: 1 addition & 1 deletion src/Caliburn.Micro.Avalonia.Tests/ViewModelLocatorTests.cs
Original file line number Diff line number Diff line change
@@ -56,7 +56,7 @@ public void ConfigureTypeMappingsShouldThrowWhenDefaultSubNamespaceForViewsIsNul


[Fact]
public void COnfigureTypeMappingsWithDefaultValuesShouldNotThrow()
public void ConfigureTypeMappingsWithDefaultValuesShouldNotThrow()
{
var typeMappingConfiguration = new TypeMappingConfiguration();

2 changes: 1 addition & 1 deletion src/Caliburn.Micro.Core.Tests/IoCTests.cs
Original file line number Diff line number Diff line change
@@ -61,7 +61,7 @@ public void A_not_initialized_GetInstance_throws_an_InvalidOperationException()
}

[Fact]
public void A_null_GetInstance_throws_a_NullRefrenceException()
public void A_null_GetInstance_throws_a_NullReferenceException()
{
using (IoCReset.Create())
{
37 changes: 11 additions & 26 deletions src/Caliburn.Micro.Core.Tests/ScreenExtentionTests.cs
Original file line number Diff line number Diff line change
@@ -12,20 +12,10 @@ public async Task Screen_ConductWithTests()
{
var root = new Screen();

var child1 = new StateScreen
{
DisplayName = "screen1"
};
var child1 = new StateScreen { DisplayName = "screen1" };
// simulate a long deactivation process
var child2 = new StateScreen(TimeSpan.FromSeconds(3))
{
DisplayName = "screen2"
};

var child3 = new StateScreen()
{
DisplayName = "screen3"
};
var child2 = new StateScreen(TimeSpan.FromSeconds(3)) { DisplayName = "screen2" };
var child3 = new StateScreen() { DisplayName = "screen3" };

child1.ConductWith(root);
child2.ConductWith(root);
@@ -49,20 +39,13 @@ public async Task Conductor_ConductWithTests()
{
var root = new Conductor<StateScreen>.Collection.AllActive();

var child1 = new StateScreen
{
DisplayName = "screen1"
};
var child1 = new StateScreen { DisplayName = "screen1" };
var child2 = new StateScreen(TimeSpan.FromSeconds(3))
{
DisplayName = "screen2",
IsClosable = false,
};

var child3 = new StateScreen()
{
DisplayName = "screen3"
};
var child3 = new StateScreen() { DisplayName = "screen3" };

root.Items.Add(child1);
root.Items.Add(child2);
@@ -81,8 +64,10 @@ public async Task Conductor_ConductWithTests()
Assert.True(child3.IsClosed, "child 3 should be closed");
}

class StateScreen : Screen
private sealed class StateScreen : Screen
{
private readonly TimeSpan? deactivationDelay;

public StateScreen()
{
}
@@ -93,7 +78,9 @@ public StateScreen(TimeSpan? deactivationDelay)
}

public bool WasActivated { get; private set; }

public bool IsClosed { get; private set; }

public bool IsClosable { get; set; }

public override Task<bool> CanCloseAsync(CancellationToken cancellationToken = default)
@@ -129,7 +116,7 @@ protected override async Task OnActivatedAsync(CancellationToken cancellationTok
IsClosable = false;
}

protected override async Task OnDeactivateAsync(bool close, CancellationToken cancellationToken = default(CancellationToken))
protected override async Task OnDeactivateAsync(bool close, CancellationToken cancellationToken = default)
{
await base.OnDeactivateAsync(close, cancellationToken);

@@ -140,8 +127,6 @@ protected override async Task OnActivatedAsync(CancellationToken cancellationTok

IsClosed = close;
}

private readonly TimeSpan? deactivationDelay;
}
}
}
36 changes: 18 additions & 18 deletions src/Caliburn.Micro.Core.Tests/SimpleContainerTests.cs
Original file line number Diff line number Diff line change
@@ -89,7 +89,7 @@ public void Null_is_returned_when_no_instance_is_found()
public class SimpleContainerRegisteringInstances
{
[Fact]
public void Instances_registed_Singleton_return_the_same_instance_for_each_call()
public void Instances_registered_Singleton_return_the_same_instance_for_each_call()
{
var container = new SimpleContainer();
container.Singleton<object>();
@@ -146,7 +146,7 @@ public void Container_Finds_Single_Constructor()

public class SingleNonEmptyConstructorType
{
public SingleNonEmptyConstructorType(SimpleContainer_Find_Constructor.SingleEmptyConstructorType type)
public SingleNonEmptyConstructorType(SingleEmptyConstructorType type)
{
}
}
@@ -165,18 +165,18 @@ public class SingleIntConstructor

public SingleIntConstructor(int x)
{
this.Value = x;
Value = x;
}
}

[Fact]
public void Container_SingleIntConstructor()
{
var container = new SimpleContainer();
container.Singleton<SingleIntConstructor>();
container.RegisterInstance(typeof(int), "x", 4);
var inst = (SingleIntConstructor)container.GetInstance(typeof(SingleIntConstructor), null);
Assert.Equal(4, inst.Value);
var sut = new SimpleContainer();
sut.Singleton<SingleIntConstructor>();
sut.RegisterInstance(typeof(int), "x", 4);
var result = (SingleIntConstructor)sut.GetInstance(typeof(SingleIntConstructor), null);
Assert.Equal(4, result.Value);
}

public class TwoConstructors
@@ -185,7 +185,7 @@ public class TwoConstructors

public TwoConstructors()
{
this.Value = 42;
Value = 42;
}

public TwoConstructors(int value)
@@ -197,20 +197,20 @@ public TwoConstructors(int value)
[Fact]
public void Container_ChooseConstructorWithRegisteredParameter()
{
var container = new SimpleContainer();
container.Singleton<TwoConstructors>();
container.RegisterInstance(typeof(int), null, 23);
var inst = (TwoConstructors)container.GetInstance(typeof(TwoConstructors), null);
Assert.Equal(23, inst.Value);
var sut = new SimpleContainer();
sut.Singleton<TwoConstructors>();
sut.RegisterInstance(typeof(int), null, 23);
var result = (TwoConstructors)sut.GetInstance(typeof(TwoConstructors), null);
Assert.Equal(23, result.Value);
}

[Fact]
public void Container_ChooseEmptyConstructorWithoutRegisteredParameter()
{
var container = new SimpleContainer();
container.Singleton<TwoConstructors>();
var inst = (TwoConstructors)container.GetInstance(typeof(TwoConstructors), null);
Assert.Equal(42, inst.Value);
var sut = new SimpleContainer();
sut.Singleton<TwoConstructors>();
var result = (TwoConstructors)sut.GetInstance(typeof(TwoConstructors), null);
Assert.Equal(42, result.Value);
}
}

4 changes: 1 addition & 3 deletions src/Caliburn.Micro.Core/AsyncEventHandler.cs
Original file line number Diff line number Diff line change
@@ -10,8 +10,6 @@ namespace Caliburn.Micro
/// <param name="sender">The source of the event.</param>
/// <param name="e">An object that contains the event data.</param>
/// <returns>A task that represents the asynchronous operation.</returns>
public delegate Task AsyncEventHandler<TEventArgs>(
object sender,
TEventArgs e)
public delegate Task AsyncEventHandler<TEventArgs>(object sender, TEventArgs e)
where TEventArgs : EventArgs;
}
73 changes: 12 additions & 61 deletions src/Caliburn.Micro.Core/BindableCollection.cs
Original file line number Diff line number Diff line change
@@ -43,14 +43,7 @@ public virtual void NotifyOfPropertyChange(string propertyName)
{
if (IsNotifying)
{
if (PlatformProvider.Current.PropertyChangeNotificationsOnUIThread)
{
OnUIThread(() => OnPropertyChanged(new PropertyChangedEventArgs(propertyName)));
}
else
{
OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
}
Execute.DispatchIfRequired(() => OnPropertyChanged(new PropertyChangedEventArgs(propertyName)));
}
}

@@ -59,21 +52,12 @@ public virtual void NotifyOfPropertyChange(string propertyName)
/// </summary>
public void Refresh()
{
if (PlatformProvider.Current.PropertyChangeNotificationsOnUIThread)
{
OnUIThread(() =>
{
OnPropertyChanged(new PropertyChangedEventArgs("Count"));
OnPropertyChanged(new PropertyChangedEventArgs("Item[]"));
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
});
}
else
Execute.DispatchIfRequired(() =>
{
OnPropertyChanged(new PropertyChangedEventArgs("Count"));
OnPropertyChanged(new PropertyChangedEventArgs("Item[]"));
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
});
}

/// <summary>
@@ -83,14 +67,7 @@ public void Refresh()
/// <param name = "item">The item to be inserted.</param>
protected override sealed void InsertItem(int index, T item)
{
if (PlatformProvider.Current.PropertyChangeNotificationsOnUIThread)
{
OnUIThread(() => InsertItemBase(index, item));
}
else
{
InsertItemBase(index, item);
}
Execute.DispatchIfRequired(() => InsertItemBase(index, item));
}

/// <summary>
@@ -113,14 +90,7 @@ protected virtual void InsertItemBase(int index, T item)
/// <param name = "item">The item to set.</param>
protected override sealed void SetItem(int index, T item)
{
if (PlatformProvider.Current.PropertyChangeNotificationsOnUIThread)
{
OnUIThread(() => SetItemBase(index, item));
}
else
{
SetItemBase(index, item);
}
Execute.DispatchIfRequired(() => SetItemBase(index, item));
}

/// <summary>
@@ -142,14 +112,7 @@ protected virtual void SetItemBase(int index, T item)
/// <param name = "index">The position used to identify the item to remove.</param>
protected override sealed void RemoveItem(int index)
{
if (PlatformProvider.Current.PropertyChangeNotificationsOnUIThread)
{
OnUIThread(() => RemoveItemBase(index));
}
else
{
RemoveItemBase(index);
}
Execute.DispatchIfRequired(() => RemoveItemBase(index));
}

/// <summary>
@@ -223,21 +186,15 @@ void AddRange()
InsertItemBase(index, item);
index++;
}

IsNotifying = previousNotificationSetting;

OnPropertyChanged(new PropertyChangedEventArgs("Count"));
OnPropertyChanged(new PropertyChangedEventArgs("Item[]"));
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}

if (PlatformProvider.Current.PropertyChangeNotificationsOnUIThread)
{
OnUIThread(AddRange);
}
else
{
AddRange();
}
Execute.DispatchIfRequired(AddRange);
}

/// <summary>
@@ -258,28 +215,22 @@ void RemoveRange()
RemoveItemBase(index);
}
}

IsNotifying = previousNotificationSetting;

OnPropertyChanged(new PropertyChangedEventArgs("Count"));
OnPropertyChanged(new PropertyChangedEventArgs("Item[]"));
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}

if (PlatformProvider.Current.PropertyChangeNotificationsOnUIThread)
{
OnUIThread(RemoveRange);
}
else
{
RemoveRange();
}
Execute.DispatchIfRequired(RemoveRange);
}

/// <summary>
/// Executes the given action on the UI thread
/// </summary>
/// <remarks>An extension point for subclasses to customise how property change notifications are handled.</remarks>
/// <remarks>An extension point for subclasses to customize how property change notifications are handled.</remarks>
/// <param name="action"></param>
protected virtual void OnUIThread(System.Action action) => action.OnUIThread();
protected virtual void OnUIThread(Action action) => action.OnUIThread();
}
}
2 changes: 1 addition & 1 deletion src/Caliburn.Micro.Core/Conductor.cs
Original file line number Diff line number Diff line change
@@ -52,7 +52,7 @@ public override async Task DeactivateItemAsync(T item, bool close, CancellationT

if (closeResult.CloseCanOccur)
{
await ChangeActiveItemAsync(default(T), close, cancellationToken);
await ChangeActiveItemAsync(default, close, cancellationToken);
}
}

4 changes: 2 additions & 2 deletions src/Caliburn.Micro.Core/ConductorBase.cs
Original file line number Diff line number Diff line change
@@ -20,7 +20,7 @@ public abstract class ConductorBase<T> : Screen, IConductor, IParent<T> where T
/// <value>The close strategy.</value>
public ICloseStrategy<T> CloseStrategy
{
get => _closeStrategy ?? (_closeStrategy = new DefaultCloseStrategy<T>());
get => _closeStrategy ??= new DefaultCloseStrategy<T>();
set => _closeStrategy = value;
}

@@ -91,7 +91,7 @@ protected virtual void OnActivationProcessed(T item, bool success)
/// <returns>The item to be activated.</returns>
protected virtual T EnsureItem(T newItem)
{
if (newItem is IChild node && !object.ReferenceEquals(node.Parent, this))
if (newItem is IChild node && !ReferenceEquals(node.Parent, this))
node.Parent = this;

return newItem;
3 changes: 2 additions & 1 deletion src/Caliburn.Micro.Core/ConductorBaseWithActiveItem.cs
Original file line number Diff line number Diff line change
@@ -7,7 +7,8 @@ namespace Caliburn.Micro
/// A base class for various implementations of <see cref="IConductor"/> that maintain an active item.
/// </summary>
/// <typeparam name="T">The type that is being conducted.</typeparam>
public abstract class ConductorBaseWithActiveItem<T> : ConductorBase<T>, IConductActiveItem where T : class
public abstract class ConductorBaseWithActiveItem<T> : ConductorBase<T>, IConductActiveItem
where T : class
{
private T _activeItem;

Loading

Unchanged files with check annotations Beta

/// <summary>
/// Navigates to the specified view model.
/// </summary>
/// <param name="viewModel">The view model to navigate to.</param>

Check warning on line 100 in src/Caliburn.Micro.Platform/Platforms/netcore-avalonia/NavigationFrame.cs

GitHub Actions / build

Parameter 'addToStack' has no matching param tag in the XML comment for 'NavigationFrame.NavigateToViewModel(object, bool)' (but other parameters do)

Check warning on line 100 in src/Caliburn.Micro.Platform/Platforms/netcore-avalonia/NavigationFrame.cs

GitHub Actions / build

Parameter 'addToStack' has no matching param tag in the XML comment for 'NavigationFrame.NavigateToViewModel(object, bool)' (but other parameters do)
private void NavigateToViewModel(object viewModel)
{
if (viewModel == null)
protected Frame RootFrame { get; private set; }
#if WinUI3
public Window Window { get; private set; }

Check warning on line 33 in src/Caliburn.Micro.Platform/Platforms/uap/CaliburnApplication.cs

GitHub Actions / build

Missing XML comment for publicly visible type or member 'CaliburnApplication.Window'

Check warning on line 33 in src/Caliburn.Micro.Platform/Platforms/uap/CaliburnApplication.cs

GitHub Actions / build

Missing XML comment for publicly visible type or member 'CaliburnApplication.Window'
#endif
/// <summary>
}
#if WinUI3
protected virtual Window CreateWindow()

Check warning on line 221 in src/Caliburn.Micro.Platform/Platforms/uap/CaliburnApplication.cs

GitHub Actions / build

Missing XML comment for publicly visible type or member 'CaliburnApplication.CreateWindow()'

Check warning on line 221 in src/Caliburn.Micro.Platform/Platforms/uap/CaliburnApplication.cs

GitHub Actions / build

Missing XML comment for publicly visible type or member 'CaliburnApplication.CreateWindow()'
{
return new Window();
}
public void InitializeWindow()

Check warning on line 227 in src/Caliburn.Micro.Platform/Platforms/uap/CaliburnApplication.cs

GitHub Actions / build

Missing XML comment for publicly visible type or member 'CaliburnApplication.InitializeWindow()'

Check warning on line 227 in src/Caliburn.Micro.Platform/Platforms/uap/CaliburnApplication.cs

GitHub Actions / build

Missing XML comment for publicly visible type or member 'CaliburnApplication.InitializeWindow()'
{
if(Window == null)
Window = CreateWindow();
/// Initializes the singleton application object. This is the first line of authored code
/// executed, and as such is the logical equivalent of main() or WinMain().
/// </summary>
public App()

Check warning on line 28 in samples/features/Features.WinUI3/App.xaml.cs

GitHub Actions / build

Non-nullable field 'container' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the field as nullable.

Check warning on line 28 in samples/features/Features.WinUI3/App.xaml.cs

GitHub Actions / build

Non-nullable field 'container' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the field as nullable.
{
this.InitializeComponent();
}