Browse Source

Merge branch 'master' into managed-file-dialog

pull/2777/head
danwalmsley 7 years ago
committed by GitHub
parent
commit
470f6467e6
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 24
      samples/ControlCatalog/MainView.xaml
  2. 1
      samples/ControlCatalog/MainWindow.xaml
  3. 9
      samples/ControlCatalog/Pages/PointersPage.cs
  4. 5
      samples/ControlCatalog/Pages/ScreenPage.cs
  5. 26
      samples/ControlCatalog/SideBar.xaml
  6. 1
      src/Avalonia.Controls/Mixins/ContentControlMixin.cs
  7. 8
      src/Avalonia.Controls/Presenters/ContentPresenter.cs
  8. 53
      tests/Avalonia.Controls.UnitTests/Presenters/ContentPresenterTests_InTemplate.cs
  9. 16
      tests/Avalonia.Controls.UnitTests/Presenters/ContentPresenterTests_Standalone.cs
  10. 17
      tests/Avalonia.Controls.UnitTests/Presenters/ContentPresenterTests_Unrooted.cs

24
samples/ControlCatalog/MainView.xaml

@ -6,10 +6,13 @@
Foreground="{DynamicResource ThemeForegroundBrush}"
FontSize="{DynamicResource FontSizeNormal}">
<Grid>
<ComboBox x:Name="Themes" SelectedIndex="0" Width="100" Margin="8" HorizontalAlignment="Right" VerticalAlignment="Bottom">
<ComboBoxItem>Light</ComboBoxItem>
<ComboBoxItem>Dark</ComboBoxItem>
</ComboBox>
<Grid.Styles>
<Style Selector="TextBlock.h2">
<Setter Property="TextWrapping" Value="Wrap"/>
<Setter Property="MaxWidth" Value="400"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
</Style>
</Grid.Styles>
<TabControl Classes="sidebar" Name="Sidebar">
<TabItem Header="AutoCompleteBox"><pages:AutoCompleteBoxPage/></TabItem>
<TabItem Header="Border"><pages:BorderPage/></TabItem>
@ -21,7 +24,12 @@
<TabItem Header="CheckBox"><pages:CheckBoxPage/></TabItem>
<TabItem Header="ComboBox"><pages:ComboBoxPage/></TabItem>
<TabItem Header="ContextMenu"><pages:ContextMenuPage/></TabItem>
<TabItem Header="DataGrid"><pages:DataGridPage/></TabItem>
<!-- DataGrid is our special snowflake -->
<TabItem Header="DataGrid"
ScrollViewer.VerticalScrollBarVisibility="Disabled"
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<pages:DataGridPage/>
</TabItem>
<TabItem Header="DatePicker"><pages:DatePickerPage/></TabItem>
<TabItem Header="Drag+Drop"><pages:DragAndDropPage/></TabItem>
<TabItem Header="Expander"><pages:ExpanderPage/></TabItem>
@ -42,6 +50,12 @@
<TabItem Header="ToolTip"><pages:ToolTipPage/></TabItem>
<TabItem Header="TreeView"><pages:TreeViewPage/></TabItem>
<TabItem Header="Viewbox"><pages:ViewboxPage/></TabItem>
<TabControl.Tag>
<ComboBox x:Name="Themes" SelectedIndex="0" Width="100" Margin="8" HorizontalAlignment="Right" VerticalAlignment="Bottom">
<ComboBoxItem>Light</ComboBoxItem>
<ComboBoxItem>Dark</ComboBoxItem>
</ComboBox>
</TabControl.Tag>
</TabControl>
</Grid>
</UserControl>

1
samples/ControlCatalog/MainWindow.xaml

@ -1,4 +1,5 @@
<Window xmlns="https://github.com/avaloniaui" MinWidth="500" MinHeight="300"
Width="1024" Height="800"
xmlns:pages="clr-namespace:ControlCatalog.Pages"
Title="Avalonia Control Gallery"
Icon="/Assets/test_icon.ico"

9
samples/ControlCatalog/Pages/PointersPage.cs

@ -69,16 +69,25 @@ namespace ControlCatalog.Pages
{
UpdatePointer(e);
e.Pointer.Capture(this);
e.Handled = true;
base.OnPointerPressed(e);
}
protected override void OnPointerMoved(PointerEventArgs e)
{
UpdatePointer(e);
e.Handled = true;
base.OnPointerMoved(e);
}
protected override void OnPointerReleased(PointerReleasedEventArgs e)
{
_pointers.Remove(e.Pointer);
e.Handled = true;
InvalidateVisual();
}
protected override void OnPointerCaptureLost(PointerCaptureLostEventArgs e)
{
_pointers.Remove(e.Pointer);
InvalidateVisual();

5
samples/ControlCatalog/Pages/ScreenPage.cs

@ -22,7 +22,10 @@ namespace ControlCatalog.Pages
public override void Render(DrawingContext context)
{
base.Render(context);
Window w = (Window)VisualRoot;
if (!(VisualRoot is Window w))
{
return;
}
var screens = w.Screens.All;
var scaling = ((IRenderRoot)w).RenderScaling;

26
samples/ControlCatalog/SideBar.xaml

@ -24,7 +24,8 @@
Name="PART_ScrollViewer"
HorizontalScrollBarVisibility="{TemplateBinding (ScrollViewer.HorizontalScrollBarVisibility)}"
VerticalScrollBarVisibility="{TemplateBinding (ScrollViewer.VerticalScrollBarVisibility)}"
Background="{TemplateBinding Background}">
Background="{TemplateBinding Background}"
DockPanel.Dock="Left">
<ItemsPresenter
Name="PART_ItemsPresenter"
Items="{TemplateBinding Items}"
@ -32,14 +33,19 @@
ItemTemplate="{TemplateBinding ItemTemplate}">
</ItemsPresenter>
</ScrollViewer>
<ContentPresenter
Name="PART_SelectedContentHost"
Margin="{TemplateBinding Padding}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
Content="{TemplateBinding SelectedContent}"
ContentTemplate="{TemplateBinding SelectedContentTemplate}">
</ContentPresenter>
<ContentControl Content="{TemplateBinding Tag}" HorizontalContentAlignment="Right" DockPanel.Dock="Bottom"/>
<ScrollViewer
HorizontalScrollBarVisibility="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=SelectedItem.(ScrollViewer.HorizontalScrollBarVisibility)}"
VerticalScrollBarVisibility="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=SelectedItem.(ScrollViewer.VerticalScrollBarVisibility)}">
<ContentPresenter
Name="PART_SelectedContentHost"
Margin="{TemplateBinding Padding}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
Content="{TemplateBinding SelectedContent}"
ContentTemplate="{TemplateBinding SelectedContentTemplate}">
</ContentPresenter>
</ScrollViewer>
</DockPanel>
</Border>
</ControlTemplate>
@ -58,6 +64,8 @@
<DoubleTransition Property="Opacity" Duration="0:0:0.150"/>
</Transitions>
</Setter>
<Setter Property="(ScrollViewer.HorizontalScrollBarVisibility)" Value="Auto"/>
<Setter Property="(ScrollViewer.VerticalScrollBarVisibility)" Value="Auto"/>
</Style>
<Style Selector="TabControl.sidebar > TabItem:pointerover">
<Setter Property="Opacity" Value="1"/>

1
src/Avalonia.Controls/Mixins/ContentControlMixin.cs

@ -150,6 +150,7 @@ namespace Avalonia.Controls.Mixins
if (oldValue is IControl child)
{
logicalChildren.Remove(child);
((ISetInheritanceParent)child).SetParent(child.Parent);
}
child = newValue as IControl;

8
src/Avalonia.Controls/Presenters/ContentPresenter.cs

@ -229,7 +229,6 @@ namespace Avalonia.Controls.Presenters
if (oldChild != null)
{
VisualChildren.Remove(oldChild);
((ISetInheritanceParent)oldChild).SetParent(oldChild.Parent);
}
if (oldChild?.Parent == this)
@ -238,7 +237,7 @@ namespace Avalonia.Controls.Presenters
// template.
LogicalChildren.Remove(oldChild);
}
else
else if (TemplatedParent != null)
{
// If we're in a ContentControl's template then invoke ChildChanging to let
// ContentControlMixin handle removing the logical child.
@ -249,6 +248,10 @@ namespace Avalonia.Controls.Presenters
newChild,
BindingPriority.LocalValue));
}
else if (oldChild != null)
{
((ISetInheritanceParent)oldChild).SetParent(oldChild.Parent);
}
}
// Set the DataContext if the data isn't a control.
@ -434,6 +437,7 @@ namespace Avalonia.Controls.Presenters
{
VisualChildren.Remove(Child);
LogicalChildren.Remove(Child);
((ISetInheritanceParent)Child).SetParent(Child.Parent);
Child = null;
_dataTemplate = null;
}

53
tests/Avalonia.Controls.UnitTests/Presenters/ContentPresenterTests_InTemplate.cs

@ -1,7 +1,11 @@
// 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 System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reactive.Linq;
using Avalonia.Controls.Presenters;
using Avalonia.Controls.Templates;
using Avalonia.Data;
@ -256,7 +260,6 @@ namespace Avalonia.Controls.UnitTests.Presenters
Assert.IsType<Canvas>(target.Child);
}
[Fact]
public void Should_Not_Bind_Old_Child_To_New_DataContext()
{
@ -281,6 +284,34 @@ namespace Avalonia.Controls.UnitTests.Presenters
target.Content = 42;
}
[Fact]
public void Should_Not_Bind_Child_To_Wrong_DataContext_When_Removing()
{
// Test for issue #2823
var canvas = new Canvas();
var (target, host) = CreateTarget();
var viewModel = new TestViewModel { Content = "foo" };
var dataContexts = new List<object>();
target.Bind(ContentPresenter.ContentProperty, (IBinding)new TemplateBinding(ContentControl.ContentProperty));
canvas.GetObservable(ContentPresenter.DataContextProperty).Subscribe(x => dataContexts.Add(x));
host.DataTemplates.Add(new FuncDataTemplate<string>((_, __) => canvas));
host.Bind(ContentControl.ContentProperty, new Binding(nameof(TestViewModel.Content)));
host.DataContext = viewModel;
Assert.Same(canvas, target.Child);
viewModel.Content = 42;
Assert.Equal(new object[]
{
null,
"foo",
null,
}, dataContexts);
}
[Fact]
public void Should_Set_InheritanceParent_Even_When_LogicalParent_Is_Already_Set()
{
@ -333,5 +364,25 @@ namespace Avalonia.Controls.UnitTests.Presenters
{
public IControl Child { get; set; }
}
private class TestViewModel : INotifyPropertyChanged
{
private object _content;
public object Content
{
get => _content;
set
{
if (_content != value)
{
_content = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Content)));
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
}
}

16
tests/Avalonia.Controls.UnitTests/Presenters/ContentPresenterTests_Standalone.cs

@ -251,5 +251,21 @@ namespace Avalonia.Controls.UnitTests.Presenters
target.Content = 42;
}
[Fact]
public void Should_Reset_InheritanceParent_When_Child_Removed()
{
var logicalParent = new Canvas();
var child = new TextBlock();
var target = new ContentPresenter();
var root = new TestRoot(target);
((ISetLogicalParent)child).SetParent(logicalParent);
target.Content = child;
target.Content = null;
// InheritanceParent is exposed via StylingParent.
Assert.Same(logicalParent, ((IStyledElement)child).StylingParent);
}
}
}

17
tests/Avalonia.Controls.UnitTests/Presenters/ContentPresenterTests_Unrooted.cs

@ -98,5 +98,22 @@ namespace Avalonia.Controls.UnitTests.Presenters
target.ApplyTemplate();
Assert.IsType<Decorator>(target.Child);
}
[Fact]
public void Should_Reset_InheritanceParent_When_Child_Removed()
{
var logicalParent = new Canvas();
var child = new TextBlock();
var target = new ContentPresenter();
((ISetLogicalParent)child).SetParent(logicalParent);
target.Content = child;
target.UpdateChild();
target.Content = null;
target.UpdateChild();
// InheritanceParent is exposed via StylingParent.
Assert.Same(logicalParent, ((IStyledElement)child).StylingParent);
}
}
}

Loading…
Cancel
Save