Browse Source

Merge branch 'master' into master

pull/1951/head
Artyom G 8 years ago
committed by GitHub
parent
commit
9cb5405ba7
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      src/Avalonia.Controls/Primitives/SelectingItemsControl.cs
  2. 34
      src/Avalonia.Visuals/Rendering/RenderLoop.cs
  3. 26
      tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests.cs
  4. 15
      tests/Avalonia.Visuals.UnitTests/Rendering/RenderLoopTests.cs

4
src/Avalonia.Controls/Primitives/SelectingItemsControl.cs

@ -289,12 +289,12 @@ namespace Avalonia.Controls.Primitives
/// <inheritdoc/>
public override void EndInit()
{
base.EndInit();
if (--_updateCount == 0)
{
UpdateFinished();
}
base.EndInit();
}
/// <summary>

34
src/Avalonia.Visuals/Rendering/RenderLoop.cs

@ -19,7 +19,8 @@ namespace Avalonia.Rendering
private readonly IDispatcher _dispatcher;
private List<IRenderLoopTask> _items = new List<IRenderLoopTask>();
private IRenderTimer _timer;
private int inTick;
private int _inTick;
private int _inUpdate;
/// <summary>
/// Initializes a new instance of the <see cref="RenderLoop"/> class.
@ -84,21 +85,36 @@ namespace Avalonia.Rendering
}
}
private async void TimerTick(TimeSpan time)
private void TimerTick(TimeSpan time)
{
if (Interlocked.CompareExchange(ref inTick, 1, 0) == 0)
if (Interlocked.CompareExchange(ref _inTick, 1, 0) == 0)
{
try
{
if (_items.Any(item => item.NeedsUpdate))
if (_items.Any(item => item.NeedsUpdate) &&
Interlocked.CompareExchange(ref _inUpdate, 1, 0) == 0)
{
await _dispatcher.InvokeAsync(() =>
_dispatcher.Post(() =>
{
foreach (var i in _items)
for (var i = 0; i < _items.Count; ++i)
{
i.Update(time);
var item = _items[i];
if (item.NeedsUpdate)
{
try
{
item.Update(time);
}
catch (Exception ex)
{
Logger.Error(LogArea.Visual, this, "Exception in render update: {Error}", ex);
}
}
}
}, DispatcherPriority.Render).ConfigureAwait(false);
Interlocked.Exchange(ref _inUpdate, 0);
}, DispatcherPriority.Render);
}
foreach (var i in _items)
@ -112,7 +128,7 @@ namespace Avalonia.Rendering
}
finally
{
Interlocked.Exchange(ref inTick, 0);
Interlocked.Exchange(ref _inTick, 0);
}
}
}

26
tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests.cs

@ -707,6 +707,26 @@ namespace Avalonia.Controls.UnitTests.Primitives
Assert.True(target.SelectedIndex == 1);
}
[Fact]
public void Binding_With_DelayedBinding_And_Initialization_Where_DataContext_Is_Root_Works()
{
// Test for #1932.
var root = new RootWithItems();
root.BeginInit();
root.DataContext = root;
var target = new ListBox();
target.BeginInit();
root.Child = target;
DelayedBinding.Add(target, ItemsControl.ItemsProperty, new Binding(nameof(RootWithItems.Items)));
DelayedBinding.Add(target, ListBox.SelectedItemProperty, new Binding(nameof(RootWithItems.Selected)));
target.EndInit();
root.EndInit();
Assert.Equal("b", target.SelectedItem);
}
private FuncControlTemplate Template()
{
@ -745,5 +765,11 @@ namespace Avalonia.Controls.UnitTests.Primitives
public IList<Item> Items { get; set; }
public Item SelectedItem { get; set; }
}
private class RootWithItems : TestRoot
{
public List<string> Items { get; set; } = new List<string>() { "a", "b", "c", "d", "e" };
public string Selected { get; set; } = "b";
}
}
}

15
tests/Avalonia.Visuals.UnitTests/Rendering/RenderLoopTests.cs

@ -19,14 +19,13 @@ namespace Avalonia.Visuals.UnitTests.Rendering
bool inDispatcher = false;
dispatcher.Setup(
d => d.InvokeAsync(It.IsAny<Action>(), DispatcherPriority.Render))
d => d.Post(It.IsAny<Action>(), DispatcherPriority.Render))
.Callback((Action a, DispatcherPriority _) =>
{
inDispatcher = true;
a();
inDispatcher = false;
})
.Returns(Task.CompletedTask);
});
var timer = new Mock<IRenderTimer>();
@ -71,14 +70,13 @@ namespace Avalonia.Visuals.UnitTests.Rendering
var dispatcher = new Mock<IDispatcher>();
bool inDispatcher = false;
dispatcher.Setup(
d => d.InvokeAsync(It.IsAny<Action>(), DispatcherPriority.Render))
d => d.Post(It.IsAny<Action>(), DispatcherPriority.Render))
.Callback((Action a, DispatcherPriority _) =>
{
inDispatcher = true;
a();
inDispatcher = false;
})
.Returns(Task.CompletedTask);
});
var timer = new Mock<IRenderTimer>();
var loop = new RenderLoop(timer.Object, dispatcher.Object);
@ -100,9 +98,8 @@ namespace Avalonia.Visuals.UnitTests.Rendering
{
var dispatcher = new Mock<IDispatcher>();
dispatcher.Setup(
d => d.InvokeAsync(It.IsAny<Action>(), DispatcherPriority.Render))
.Callback((Action a, DispatcherPriority _) => a())
.Returns(Task.CompletedTask);
d => d.Post(It.IsAny<Action>(), DispatcherPriority.Render))
.Callback((Action a, DispatcherPriority _) => a());
var timer = new Mock<IRenderTimer>();
var loop = new RenderLoop(timer.Object, dispatcher.Object);

Loading…
Cancel
Save