Browse Source

Merge branch 'master' into fixes/829-findcontrol-returns-null-for-usercontrol

pull/843/head
Steven Kirk 9 years ago
committed by GitHub
parent
commit
331fa3ac1a
  1. 14
      src/Avalonia.Controls/Presenters/ItemVirtualizer.cs
  2. 11
      src/Avalonia.Controls/Presenters/TextPresenter.cs
  3. 4
      src/Avalonia.Controls/ScrollViewer.cs
  4. 4
      src/Markup/Avalonia.Markup.Xaml/Data/Binding.cs
  5. 1
      src/Markup/Avalonia.Markup.Xaml/Data/RelativeSource.cs
  6. 2
      src/Markup/Avalonia.Markup/Data/MarkupBindingChainException.cs
  7. 5
      src/Windows/Avalonia.Win32/WindowImpl.cs
  8. 18
      tests/Avalonia.Controls.UnitTests/ListBoxTests.cs
  9. 5
      tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests_Virtualization.cs
  10. 1
      tests/Avalonia.Markup.Xaml.UnitTests/Avalonia.Markup.Xaml.UnitTests.csproj
  11. 63
      tests/Avalonia.Markup.Xaml.UnitTests/Data/BindingTests_Self.cs
  12. 44
      tests/Avalonia.Markup.Xaml.UnitTests/Xaml/BindingTests.cs

14
src/Avalonia.Controls/Presenters/ItemVirtualizer.cs

@ -4,6 +4,7 @@
using System;
using System.Collections;
using System.Collections.Specialized;
using System.Reactive.Linq;
using Avalonia.Controls.Primitives;
using Avalonia.Controls.Utils;
using Avalonia.Input;
@ -17,6 +18,7 @@ namespace Avalonia.Controls.Presenters
internal abstract class ItemVirtualizer : IVirtualizingController, IDisposable
{
private double _crossAxisOffset;
private IDisposable _subscriptions;
/// <summary>
/// Initializes a new instance of the <see cref="ItemVirtualizer"/> class.
@ -27,6 +29,15 @@ namespace Avalonia.Controls.Presenters
Owner = owner;
Items = owner.Items;
ItemCount = owner.Items.Count();
var panel = VirtualizingPanel;
if (panel != null)
{
_subscriptions = panel.GetObservable(Panel.BoundsProperty)
.Skip(1)
.Subscribe(_ => InvalidateScroll());
}
}
/// <summary>
@ -240,6 +251,9 @@ namespace Avalonia.Controls.Presenters
/// <inheritdoc/>
public virtual void Dispose()
{
_subscriptions?.Dispose();
_subscriptions = null;
if (VirtualizingPanel != null)
{
VirtualizingPanel.Controller = null;

11
src/Avalonia.Controls/Presenters/TextPresenter.cs

@ -173,10 +173,13 @@ namespace Avalonia.Controls.Presenters
{
if (this.GetVisualParent() != null)
{
_caretBlink = true;
_caretTimer.Stop();
_caretTimer.Start();
InvalidateVisual();
if (_caretTimer.IsEnabled)
{
_caretBlink = true;
_caretTimer.Stop();
_caretTimer.Start();
InvalidateVisual();
}
if (IsMeasureValid)
{

4
src/Avalonia.Controls/ScrollViewer.cs

@ -157,10 +157,6 @@ namespace Avalonia.Controls
/// </summary>
public ScrollViewer()
{
Observable.CombineLatest(
this.GetObservable(ExtentProperty),
this.GetObservable(ViewportProperty))
.Select(x => new { Extent = x[0], Viewport = x[1] });
}
/// <summary>

4
src/Markup/Avalonia.Markup.Xaml/Data/Binding.cs

@ -115,6 +115,10 @@ namespace Avalonia.Markup.Xaml.Data
anchor,
enableDataValidation);
}
else if (RelativeSource.Mode == RelativeSourceMode.Self)
{
observer = CreateSourceObserver(target, pathInfo.Path, enableDataValidation);
}
else if (RelativeSource.Mode == RelativeSourceMode.TemplatedParent)
{
observer = CreateTemplatedParentObserver(target, pathInfo.Path);

1
src/Markup/Avalonia.Markup.Xaml/Data/RelativeSource.cs

@ -5,6 +5,7 @@ namespace Avalonia.Markup.Xaml.Data
{
public enum RelativeSourceMode
{
Self,
DataContext,
TemplatedParent,
}

2
src/Markup/Avalonia.Markup/Data/MarkupBindingChainException.cs

@ -26,7 +26,7 @@ namespace Avalonia.Markup.Data
_nodes = null;
}
public bool HasNodes => _nodes.Count > 0;
public bool HasNodes => _nodes?.Count > 0;
public void AddNode(string node) => _nodes.Add(node);
public void Commit(string expression)

5
src/Windows/Avalonia.Win32/WindowImpl.cs

@ -709,7 +709,10 @@ namespace Avalonia.Win32
MaximizeWithoutCoveringTaskbar();
}
SetFocus(_hwnd);
if (!Design.IsDesignMode)
{
SetFocus(_hwnd);
}
}
private void MaximizeWithoutCoveringTaskbar()

18
tests/Avalonia.Controls.UnitTests/ListBoxTests.cs

@ -153,6 +153,23 @@ namespace Avalonia.Controls.UnitTests
Assert.False(((ListBoxItem)target.Presenter.Panel.Children[0]).IsSelected);
}
[Fact]
public void ScrollViewer_Should_Have_Correct_Extent_And_Viewport()
{
var target = new ListBox
{
Template = ListBoxTemplate(),
Items = Enumerable.Range(0, 20).Select(x => $"Item {x}").ToList(),
ItemTemplate = new FuncDataTemplate<string>(x => new TextBlock { Width = 20, Height = 10 }),
SelectedIndex = 0,
};
Prepare(target);
Assert.Equal(new Size(20, 20), target.Scroll.Extent);
Assert.Equal(new Size(100, 10), target.Scroll.Viewport);
}
private FuncControlTemplate ListBoxTemplate()
{
return new FuncControlTemplate<ListBox>(parent =>
@ -233,6 +250,7 @@ namespace Avalonia.Controls.UnitTests
i.InvalidateMeasure();
}
target.Measure(new Size(100, 100));
target.Arrange(new Rect(0, 0, 100, 100));
}

5
tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests_Virtualization.cs

@ -4,7 +4,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Avalonia.Collections;
using Avalonia.Controls.Generators;
using Avalonia.Controls.Presenters;
using Avalonia.Controls.Primitives;
@ -113,7 +112,7 @@ namespace Avalonia.Controls.UnitTests.Presenters
var scroll = (ScrollContentPresenter)target.Parent;
Assert.Equal(new Size(10, 20), scroll.Extent);
Assert.Equal(new Size(0, 10), scroll.Viewport);
Assert.Equal(new Size(100, 10), scroll.Viewport);
}
[Fact]
@ -255,7 +254,7 @@ namespace Avalonia.Controls.UnitTests.Presenters
Assert.Equal(10, target.Panel.Children.Count);
Assert.Equal(new Size(10, 20), scroll.Extent);
Assert.Equal(new Size(0, 10), scroll.Viewport);
Assert.Equal(new Size(100, 10), scroll.Viewport);
target.VirtualizationMode = ItemVirtualizationMode.None;
target.Measure(new Size(100, 100));

1
tests/Avalonia.Markup.Xaml.UnitTests/Avalonia.Markup.Xaml.UnitTests.csproj

@ -96,6 +96,7 @@
<Compile Include="Data\BindingTests_DataValidation.cs" />
<Compile Include="Data\BindingTests_Source.cs" />
<Compile Include="Data\BindingTests_ElementName.cs" />
<Compile Include="Data\BindingTests_Self.cs" />
<Compile Include="Data\MultiBindingTests.cs" />
<Compile Include="Data\BindingTests_TemplatedParent.cs" />
<Compile Include="Data\BindingTests.cs" />

63
tests/Avalonia.Markup.Xaml.UnitTests/Data/BindingTests_Self.cs

@ -0,0 +1,63 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
using Moq;
using Avalonia.Controls;
using Avalonia.Data;
using Avalonia.Markup.Xaml.Data;
using Avalonia.Styling;
using Xunit;
using System.Reactive.Disposables;
namespace Avalonia.Markup.Xaml.UnitTests.Data
{
public class BindingTests_Self
{
[Fact]
public void Binding_To_Property_On_Self_Should_Work()
{
var target = new TextBlock
{
Tag = "Hello World!",
[!TextBlock.TextProperty] = new Binding("Tag")
{
RelativeSource = new RelativeSource(RelativeSourceMode.Self)
},
};
Assert.Equal("Hello World!", target.Text);
}
[Fact]
public void TwoWay_Binding_To_Property_On_Self_Should_Work()
{
var target = new TextBlock
{
Tag = "Hello World!",
[!TextBlock.TextProperty] = new Binding("Tag", BindingMode.TwoWay)
{
RelativeSource = new RelativeSource(RelativeSourceMode.Self)
},
};
Assert.Equal("Hello World!", target.Text);
target.Text = "Goodbye cruel world :(";
Assert.Equal("Goodbye cruel world :(", target.Text);
}
private Mock<IControl> CreateTarget(
ITemplatedControl templatedParent = null,
string text = null)
{
var result = new Mock<IControl>();
result.Setup(x => x.GetValue(Control.TemplatedParentProperty)).Returns(templatedParent);
result.Setup(x => x.GetValue((AvaloniaProperty)Control.TemplatedParentProperty)).Returns(templatedParent);
result.Setup(x => x.GetValue((AvaloniaProperty)TextBox.TextProperty)).Returns(text);
result.Setup(x => x.Bind(It.IsAny<AvaloniaProperty>(), It.IsAny<IObservable<object>>(), It.IsAny<BindingPriority>()))
.Returns(Disposable.Empty);
return result;
}
}
}

44
tests/Avalonia.Markup.Xaml.UnitTests/Xaml/BindingTests.cs

@ -145,5 +145,49 @@ namespace Avalonia.Markup.Xaml.UnitTests.Xaml
Assert.Equal("foo", border.DataContext);
}
}
[Fact(Skip = "OmniXaml doesn't support nested markup extensions. #119")]
public void Binding_To_Self_Works()
{
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
var xaml = @"
<Window xmlns='https://github.com/avaloniaui'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
<TextBlock Name='textblock' Text='{Binding Tag, RelativeSource={RelativeSource Self}}'/>
</Window>";
var loader = new AvaloniaXamlLoader();
var window = (Window)loader.Load(xaml);
var textBlock = (TextBlock)window.Content;
window.ApplyTemplate();
Assert.Equal("foo", textBlock.Text);
}
}
[Fact]
public void Longform_Binding_To_Self_Works()
{
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
var xaml = @"
<Window xmlns='https://github.com/avaloniaui'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
<TextBlock Name='textblock' Tag='foo'>
<TextBlock.Text>
<Binding RelativeSource='{RelativeSource Self}' Path='Tag'/>
</TextBlock.Text>
</TextBlock>
</Window>";
var loader = new AvaloniaXamlLoader();
var window = (Window)loader.Load(xaml);
var textBlock = (TextBlock)window.Content;
window.ApplyTemplate();
Assert.Equal("foo", textBlock.Text);
}
}
}
}

Loading…
Cancel
Save