Conductors, which override CanCloseAsync, must call CanClose

Otherwise subclasses which override CanClose but not CanCloseAsync won't
work as expected.

Fixes #10
This commit is contained in:
Antony Male 2016-07-09 12:43:53 +01:00
parent 3286bf087e
commit b6b9811ab0
9 changed files with 113 additions and 10 deletions

View File

@ -56,6 +56,8 @@ namespace Stylet
/// <returns>Task indicating whether this can be closed</returns>
public override Task<bool> CanCloseAsync()
{
if (!this.CanClose())
return Task.FromResult(false);
return this.CanCloseItem(this.ActiveItem);
}
}

View File

@ -122,6 +122,8 @@ namespace Stylet
/// <returns>A Task indicating whether this conductor can close</returns>
public override Task<bool> CanCloseAsync()
{
if (!this.CanClose())
return Task.FromResult(false);
return this.CanAllItemsCloseAsync(this.items);
}

View File

@ -67,8 +67,15 @@ namespace Stylet
/// <returns>Task indicating whether all items can close</returns>
protected virtual async Task<bool> CanAllItemsCloseAsync(IEnumerable<T> itemsToClose)
{
var results = await Task.WhenAll(itemsToClose.Select(this.CanCloseItem));
return results.All(x => x);
// We need to call these in order: we don't want them all do show "are you sure you
// want to close" dialogs at once, for instance.
foreach (var itemToClose in itemsToClose)
{
if (!await this.CanCloseItem(itemToClose))
return false;
}
return true;
}
/// <summary>

View File

@ -92,6 +92,8 @@ namespace Stylet
/// <returns>A task indicating whether this conductor can close</returns>
public override Task<bool> CanCloseAsync()
{
if (!this.CanClose())
return Task.FromResult(false);
return this.CanAllItemsCloseAsync(this.history.Concat(new[] { this.ActiveItem }));
}

View File

@ -170,6 +170,8 @@ namespace Stylet
/// <returns>A task indicating whether this conductor can close</returns>
public override Task<bool> CanCloseAsync()
{
if (!this.CanClose())
return Task.FromResult(false);
return this.CanAllItemsCloseAsync(this.items);
}

View File

@ -12,12 +12,21 @@ namespace StyletUnitTests
public interface IMyScreen : IScreen, IDisposable
{ }
private Conductor<IScreen>.Collection.AllActive conductor;
private class MyConductor : Conductor<IScreen>.Collection.AllActive
{
public bool CanCloseValue = true;
protected override bool CanClose()
{
return this.CanCloseValue;
}
}
private MyConductor conductor;
[SetUp]
public void SetUp()
{
this.conductor = new Conductor<IScreen>.Collection.AllActive();
this.conductor = new MyConductor();
}
[Test]
@ -116,6 +125,19 @@ namespace StyletUnitTests
Assert.IsFalse(this.conductor.CanCloseAsync().Result);
}
[Test]
public void ConductorCanCloseAsyncCallsCanCloseOnSelfBeforeChildren()
{
var screen = new Mock<IScreen>();
this.conductor.ActivateItem(screen.Object);
this.conductor.CanCloseValue = false;
Assert.IsFalse(this.conductor.CanCloseAsync().Result);
screen.Verify(x => x.CanCloseAsync(), Times.Never());
}
[Test]
public void AddingItemActivatesAndSetsParent()
{

View File

@ -12,12 +12,21 @@ namespace StyletUnitTests
public interface IMyScreen : IScreen, IDisposable
{ }
private Conductor<IScreen>.StackNavigation conductor;
private class MyConductor : Conductor<IScreen>.StackNavigation
{
public bool CanCloseValue = true;
protected override bool CanClose()
{
return this.CanCloseValue;
}
}
private MyConductor conductor;
[SetUp]
public void SetUp()
{
this.conductor = new Conductor<IScreen>.StackNavigation();
this.conductor = new MyConductor();
}
[Test]
@ -200,6 +209,19 @@ namespace StyletUnitTests
Assert.IsFalse(this.conductor.CanCloseAsync().Result);
}
[Test]
public void ConductorCanCloseAsyncCallsCanCloseOnSelfBeforeChildren()
{
var screen = new Mock<IScreen>();
this.conductor.ActivateItem(screen.Object);
this.conductor.CanCloseValue = false;
Assert.IsFalse(this.conductor.CanCloseAsync().Result);
screen.Verify(x => x.CanCloseAsync(), Times.Never());
}
[Test]
public void DeactivatingActiveItemGoesBack()
{

View File

@ -12,12 +12,21 @@ namespace StyletUnitTests
public interface IMyScreen : IScreen, IDisposable
{ }
private Conductor<IScreen>.Collection.OneActive conductor;
private class MyConductor : Conductor<IScreen>.Collection.OneActive
{
public bool CanCloseValue = true;
protected override bool CanClose()
{
return this.CanCloseValue;
}
}
private MyConductor conductor;
[SetUp]
public void SetUp()
{
this.conductor = new Conductor<IScreen>.Collection.OneActive();
this.conductor = new MyConductor();
}
[Test]
@ -166,6 +175,19 @@ namespace StyletUnitTests
Assert.IsFalse(this.conductor.CanCloseAsync().Result);
}
[Test]
public void ConductorCanCloseAsyncCallsCanCloseOnSelfBeforeChildren()
{
var screen = new Mock<IScreen>();
this.conductor.ActivateItem(screen.Object);
this.conductor.CanCloseValue = false;
Assert.IsFalse(this.conductor.CanCloseAsync().Result);
screen.Verify(x => x.CanCloseAsync(), Times.Never());
}
[Test]
public void AddingItemSetsParent()
{

View File

@ -12,12 +12,21 @@ namespace StyletUnitTests
public interface IMyScreen : IScreen, IDisposable
{ }
private Conductor<IScreen> conductor;
private class MyConductor : Conductor<IScreen>
{
public bool CanCloseValue = true;
protected override bool CanClose()
{
return this.CanCloseValue;
}
}
private MyConductor conductor;
[SetUp]
public void SetUp()
{
this.conductor = new Conductor<IScreen>();
this.conductor = new MyConductor();
}
[Test]
@ -183,6 +192,19 @@ namespace StyletUnitTests
Assert.IsFalse(this.conductor.CanCloseAsync().Result);
}
[Test]
public void ConductorCanCloseAsyncCallsCanCloseOnSelfBeforeChildren()
{
var screen = new Mock<IScreen>();
this.conductor.ActivateItem(screen.Object);
this.conductor.CanCloseValue = false;
Assert.IsFalse(this.conductor.CanCloseAsync().Result);
screen.Verify(x => x.CanCloseAsync(), Times.Never());
}
[Test]
public void ClosingConductorClosesActiveItem()
{