From 2fa8247f014af936577b1dbaf6372d281fbb168c Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Thu, 27 Jun 2019 10:55:27 +0200 Subject: [PATCH 1/2] Removed MemberSelector. --- .../Pages/AutoCompleteBoxPage.xaml | 4 - samples/ControlCatalog/SideBar.xaml | 3 +- samples/RenderDemo/SideBar.xaml | 5 +- src/Avalonia.Controls/AutoCompleteBox.cs | 26 --- src/Avalonia.Controls/ComboBox.cs | 3 +- .../Generators/IItemContainerGenerator.cs | 12 +- .../Generators/ItemContainerGenerator.cs | 17 +- .../Generators/ItemContainerGenerator`1.cs | 14 +- .../Generators/TreeItemContainerGenerator.cs | 5 +- src/Avalonia.Controls/ItemsControl.cs | 15 -- .../Presenters/CarouselPresenter.cs | 2 +- .../Presenters/ItemContainerSync.cs | 2 +- .../Presenters/ItemVirtualizerNone.cs | 2 +- .../Presenters/ItemVirtualizerSimple.cs | 9 +- .../Presenters/ItemsPresenterBase.cs | 15 -- src/Avalonia.Controls/Primitives/TabStrip.cs | 9 - .../Templates/FuncMemberSelector.cs | 35 ---- .../Templates/IMemberSelector.cs | 18 -- .../AutoCompleteBox.xaml | 1 - src/Avalonia.Themes.Default/Carousel.xaml | 3 +- src/Avalonia.Themes.Default/ComboBox.xaml | 1 - .../DataValidationErrors.xaml | 2 +- src/Avalonia.Themes.Default/ItemsControl.xaml | 5 +- src/Avalonia.Themes.Default/ListBox.xaml | 3 +- src/Avalonia.Themes.Default/MenuItem.xaml | 6 +- src/Avalonia.Themes.Default/TabControl.xaml | 3 +- src/Avalonia.Themes.Default/TabStrip.xaml | 3 +- src/Avalonia.Themes.Default/TreeView.xaml | 3 +- src/Avalonia.Themes.Default/TreeViewItem.xaml | 3 +- .../Avalonia.Markup.Xaml.csproj | 2 - .../Converters/MemberSelectorTypeConverter.cs | 24 --- .../Templates/MemberSelector.cs | 48 ------ .../AvaloniaXamlIlLanguage.cs | 2 - .../Generators/ItemContainerGeneratorTests.cs | 6 +- .../ItemContainerGeneratorTypedTests.cs | 2 +- .../ItemsControlTests.cs | 22 --- .../Presenters/ItemsPresenterTests.cs | 40 ----- .../Primitives/TabStripTests.cs | 55 ------ .../Avalonia.LeakTests/MemberSelectorTests.cs | 55 ------ .../Templates/MemberSelectorTests.cs | 159 ------------------ .../AutoDataTemplateBindingHookTest.cs | 3 +- 41 files changed, 36 insertions(+), 611 deletions(-) delete mode 100644 src/Avalonia.Controls/Templates/FuncMemberSelector.cs delete mode 100644 src/Avalonia.Controls/Templates/IMemberSelector.cs delete mode 100644 src/Markup/Avalonia.Markup.Xaml/Converters/MemberSelectorTypeConverter.cs delete mode 100644 src/Markup/Avalonia.Markup.Xaml/Templates/MemberSelector.cs delete mode 100644 tests/Avalonia.LeakTests/MemberSelectorTests.cs delete mode 100644 tests/Avalonia.Markup.Xaml.UnitTests/Templates/MemberSelectorTests.cs diff --git a/samples/ControlCatalog/Pages/AutoCompleteBoxPage.xaml b/samples/ControlCatalog/Pages/AutoCompleteBoxPage.xaml index 0ca3567970..f90a0c4658 100644 --- a/samples/ControlCatalog/Pages/AutoCompleteBoxPage.xaml +++ b/samples/ControlCatalog/Pages/AutoCompleteBoxPage.xaml @@ -37,10 +37,6 @@ - - + ItemTemplate="{TemplateBinding ItemTemplate}"> + ItemTemplate="{TemplateBinding ItemTemplate}"> - \ No newline at end of file + diff --git a/src/Avalonia.Controls/AutoCompleteBox.cs b/src/Avalonia.Controls/AutoCompleteBox.cs index b87e10d284..787abc1891 100644 --- a/src/Avalonia.Controls/AutoCompleteBox.cs +++ b/src/Avalonia.Controls/AutoCompleteBox.cs @@ -345,7 +345,6 @@ namespace Avalonia.Controls /// private IDisposable _collectionChangeSubscription; - private IMemberSelector _valueMemberSelector; private Func>> _asyncPopulator; private CancellationTokenSource _populationCancellationTokenSource; @@ -541,12 +540,6 @@ namespace Avalonia.Controls o => o.Items, (o, v) => o.Items = v); - public static readonly DirectProperty ValueMemberSelectorProperty = - AvaloniaProperty.RegisterDirect( - nameof(ValueMemberSelector), - o => o.ValueMemberSelector, - (o, v) => o.ValueMemberSelector = v); - public static readonly DirectProperty>>> AsyncPopulatorProperty = AvaloniaProperty.RegisterDirect>>>( nameof(AsyncPopulator), @@ -958,20 +951,6 @@ namespace Avalonia.Controls } } - /// - /// Gets or sets the MemberSelector that is used to get values for - /// display in the text portion of the - /// control. - /// - /// The MemberSelector that is used to get values for display in - /// the text portion of the - /// control. - public IMemberSelector ValueMemberSelector - { - get { return _valueMemberSelector; } - set { SetAndRaise(ValueMemberSelectorProperty, ref _valueMemberSelector, value); } - } - /// /// Gets or sets the selected item in the drop-down. /// @@ -1841,11 +1820,6 @@ namespace Avalonia.Controls return _valueBindingEvaluator.GetDynamicValue(value) ?? String.Empty; } - if (_valueMemberSelector != null) - { - value = _valueMemberSelector.Select(value); - } - return value == null ? String.Empty : value.ToString(); } diff --git a/src/Avalonia.Controls/ComboBox.cs b/src/Avalonia.Controls/ComboBox.cs index 5d427df5a6..f32b8fabc6 100644 --- a/src/Avalonia.Controls/ComboBox.cs +++ b/src/Avalonia.Controls/ComboBox.cs @@ -333,8 +333,7 @@ namespace Avalonia.Controls } else { - var selector = MemberSelector; - SelectionBoxItem = selector != null ? selector.Select(item) : item; + SelectionBoxItem = item; } } diff --git a/src/Avalonia.Controls/Generators/IItemContainerGenerator.cs b/src/Avalonia.Controls/Generators/IItemContainerGenerator.cs index 653a4f5dcb..2d6757219d 100644 --- a/src/Avalonia.Controls/Generators/IItemContainerGenerator.cs +++ b/src/Avalonia.Controls/Generators/IItemContainerGenerator.cs @@ -49,12 +49,8 @@ namespace Avalonia.Controls.Generators /// The index of the item of data in the control's items. /// /// The item. - /// An optional member selector. /// The created controls. - ItemContainerInfo Materialize( - int index, - object item, - IMemberSelector selector); + ItemContainerInfo Materialize(int index, object item); /// /// Removes a set of created containers. @@ -84,11 +80,7 @@ namespace Avalonia.Controls.Generators /// The removed containers. IEnumerable RemoveRange(int startingIndex, int count); - bool TryRecycle( - int oldIndex, - int newIndex, - object item, - IMemberSelector selector); + bool TryRecycle(int oldIndex, int newIndex, object item); /// /// Clears all created containers and returns the removed controls. diff --git a/src/Avalonia.Controls/Generators/ItemContainerGenerator.cs b/src/Avalonia.Controls/Generators/ItemContainerGenerator.cs index f1a1f94a01..4fd6f4135c 100644 --- a/src/Avalonia.Controls/Generators/ItemContainerGenerator.cs +++ b/src/Avalonia.Controls/Generators/ItemContainerGenerator.cs @@ -54,13 +54,9 @@ namespace Avalonia.Controls.Generators public virtual Type ContainerType => null; /// - public ItemContainerInfo Materialize( - int index, - object item, - IMemberSelector selector) + public ItemContainerInfo Materialize(int index, object item) { - var i = selector != null ? selector.Select(item) : item; - var container = new ItemContainerInfo(CreateContainer(i), item, index); + var container = new ItemContainerInfo(CreateContainer(item), item, index); _containers.Add(container.Index, container); Materialized?.Invoke(this, new ItemContainerEventArgs(container)); @@ -138,14 +134,7 @@ namespace Avalonia.Controls.Generators } /// - public virtual bool TryRecycle( - int oldIndex, - int newIndex, - object item, - IMemberSelector selector) - { - return false; - } + public virtual bool TryRecycle(int oldIndex, int newIndex, object item) => false; /// public virtual IEnumerable Clear() diff --git a/src/Avalonia.Controls/Generators/ItemContainerGenerator`1.cs b/src/Avalonia.Controls/Generators/ItemContainerGenerator`1.cs index 320d6c8faf..d1d1c2b172 100644 --- a/src/Avalonia.Controls/Generators/ItemContainerGenerator`1.cs +++ b/src/Avalonia.Controls/Generators/ItemContainerGenerator`1.cs @@ -79,11 +79,7 @@ namespace Avalonia.Controls.Generators } /// - public override bool TryRecycle( - int oldIndex, - int newIndex, - object item, - IMemberSelector selector) + public override bool TryRecycle(int oldIndex, int newIndex, object item) { var container = ContainerFromIndex(oldIndex); @@ -92,16 +88,14 @@ namespace Avalonia.Controls.Generators throw new IndexOutOfRangeException("Could not recycle container: not materialized."); } - var i = selector != null ? selector.Select(item) : item; - - container.SetValue(ContentProperty, i); + container.SetValue(ContentProperty, item); if (!(item is IControl)) { - container.DataContext = i; + container.DataContext = item; } - var info = MoveContainer(oldIndex, newIndex, i); + var info = MoveContainer(oldIndex, newIndex, item); RaiseRecycled(new ItemContainerEventArgs(info)); return true; diff --git a/src/Avalonia.Controls/Generators/TreeItemContainerGenerator.cs b/src/Avalonia.Controls/Generators/TreeItemContainerGenerator.cs index 304c86dbf7..fce7579ec0 100644 --- a/src/Avalonia.Controls/Generators/TreeItemContainerGenerator.cs +++ b/src/Avalonia.Controls/Generators/TreeItemContainerGenerator.cs @@ -118,10 +118,7 @@ namespace Avalonia.Controls.Generators return base.RemoveRange(startingIndex, count); } - public override bool TryRecycle(int oldIndex, int newIndex, object item, IMemberSelector selector) - { - return false; - } + public override bool TryRecycle(int oldIndex, int newIndex, object item) => false; private ITreeDataTemplate GetTreeDataTemplate(object item, IDataTemplate primary) { diff --git a/src/Avalonia.Controls/ItemsControl.cs b/src/Avalonia.Controls/ItemsControl.cs index a292ff7d0a..902e55bde6 100644 --- a/src/Avalonia.Controls/ItemsControl.cs +++ b/src/Avalonia.Controls/ItemsControl.cs @@ -54,12 +54,6 @@ namespace Avalonia.Controls public static readonly StyledProperty ItemTemplateProperty = AvaloniaProperty.Register(nameof(ItemTemplate)); - /// - /// Defines the property. - /// - public static readonly StyledProperty MemberSelectorProperty = - AvaloniaProperty.Register(nameof(MemberSelector)); - private IEnumerable _items = new AvaloniaList(); private int _itemCount; private IItemContainerGenerator _itemContainerGenerator; @@ -144,15 +138,6 @@ namespace Avalonia.Controls set { SetValue(ItemTemplateProperty, value); } } - /// - /// Selects a member from to use as the list item. - /// - public IMemberSelector MemberSelector - { - get { return GetValue(MemberSelectorProperty); } - set { SetValue(MemberSelectorProperty, value); } - } - /// /// Gets the items presenter control. /// diff --git a/src/Avalonia.Controls/Presenters/CarouselPresenter.cs b/src/Avalonia.Controls/Presenters/CarouselPresenter.cs index a3123cf8c6..dedab3e43e 100644 --- a/src/Avalonia.Controls/Presenters/CarouselPresenter.cs +++ b/src/Avalonia.Controls/Presenters/CarouselPresenter.cs @@ -213,7 +213,7 @@ namespace Avalonia.Controls.Presenters if (container == null && IsVirtualized) { var item = Items.Cast().ElementAt(index); - var materialized = ItemContainerGenerator.Materialize(index, item, MemberSelector); + var materialized = ItemContainerGenerator.Materialize(index, item); Panel.Children.Add(materialized.ContainerControl); container = materialized.ContainerControl; } diff --git a/src/Avalonia.Controls/Presenters/ItemContainerSync.cs b/src/Avalonia.Controls/Presenters/ItemContainerSync.cs index 035d404dec..6e72908e6b 100644 --- a/src/Avalonia.Controls/Presenters/ItemContainerSync.cs +++ b/src/Avalonia.Controls/Presenters/ItemContainerSync.cs @@ -88,7 +88,7 @@ namespace Avalonia.Controls.Presenters foreach (var item in items) { - var i = generator.Materialize(index++, item, owner.MemberSelector); + var i = generator.Materialize(index++, item); if (i.ContainerControl != null) { diff --git a/src/Avalonia.Controls/Presenters/ItemVirtualizerNone.cs b/src/Avalonia.Controls/Presenters/ItemVirtualizerNone.cs index 413855bcc6..56f64779f6 100644 --- a/src/Avalonia.Controls/Presenters/ItemVirtualizerNone.cs +++ b/src/Avalonia.Controls/Presenters/ItemVirtualizerNone.cs @@ -90,7 +90,7 @@ namespace Avalonia.Controls.Presenters foreach (var item in items) { - var i = generator.Materialize(index++, item, Owner.MemberSelector); + var i = generator.Materialize(index++, item); if (i.ContainerControl != null) { diff --git a/src/Avalonia.Controls/Presenters/ItemVirtualizerSimple.cs b/src/Avalonia.Controls/Presenters/ItemVirtualizerSimple.cs index d11ce9a7ea..b8b8094582 100644 --- a/src/Avalonia.Controls/Presenters/ItemVirtualizerSimple.cs +++ b/src/Avalonia.Controls/Presenters/ItemVirtualizerSimple.cs @@ -314,7 +314,6 @@ namespace Avalonia.Controls.Presenters if (!panel.IsFull && Items != null && panel.IsAttachedToVisualTree) { - var memberSelector = Owner.MemberSelector; var index = NextIndex; var step = 1; @@ -337,7 +336,7 @@ namespace Avalonia.Controls.Presenters } } - var materialized = generator.Materialize(index, Items.ElementAt(index), memberSelector); + var materialized = generator.Materialize(index, Items.ElementAt(index)); if (step == 1) { @@ -383,7 +382,6 @@ namespace Avalonia.Controls.Presenters { var panel = VirtualizingPanel; var generator = Owner.ItemContainerGenerator; - var selector = Owner.MemberSelector; var containers = generator.Containers.ToList(); var itemIndex = FirstIndex; @@ -393,7 +391,7 @@ namespace Avalonia.Controls.Presenters if (!object.Equals(container.Item, item)) { - if (!generator.TryRecycle(itemIndex, itemIndex, item, selector)) + if (!generator.TryRecycle(itemIndex, itemIndex, item)) { throw new NotImplementedException(); } @@ -420,7 +418,6 @@ namespace Avalonia.Controls.Presenters { var panel = VirtualizingPanel; var generator = Owner.ItemContainerGenerator; - var selector = Owner.MemberSelector; //validate delta it should never overflow last index or generate index < 0 delta = MathUtilities.Clamp(delta, -FirstIndex, ItemCount - FirstIndex - panel.Children.Count); @@ -437,7 +434,7 @@ namespace Avalonia.Controls.Presenters var item = Items.ElementAt(newItemIndex); - if (!generator.TryRecycle(oldItemIndex, newItemIndex, item, selector)) + if (!generator.TryRecycle(oldItemIndex, newItemIndex, item)) { throw new NotImplementedException(); } diff --git a/src/Avalonia.Controls/Presenters/ItemsPresenterBase.cs b/src/Avalonia.Controls/Presenters/ItemsPresenterBase.cs index b4b792139d..ea56a0c6fc 100644 --- a/src/Avalonia.Controls/Presenters/ItemsPresenterBase.cs +++ b/src/Avalonia.Controls/Presenters/ItemsPresenterBase.cs @@ -35,12 +35,6 @@ namespace Avalonia.Controls.Presenters public static readonly StyledProperty ItemTemplateProperty = ItemsControl.ItemTemplateProperty.AddOwner(); - /// - /// Defines the property. - /// - public static readonly StyledProperty MemberSelectorProperty = - ItemsControl.MemberSelectorProperty.AddOwner(); - private IEnumerable _items; private IDisposable _itemsSubscription; private bool _createdPanel; @@ -127,15 +121,6 @@ namespace Avalonia.Controls.Presenters set { SetValue(ItemTemplateProperty, value); } } - /// - /// Selects a member from to use as the list item. - /// - public IMemberSelector MemberSelector - { - get { return GetValue(MemberSelectorProperty); } - set { SetValue(MemberSelectorProperty, value); } - } - /// /// Gets the panel used to display the items. /// diff --git a/src/Avalonia.Controls/Primitives/TabStrip.cs b/src/Avalonia.Controls/Primitives/TabStrip.cs index 0e15ae4d7b..a61757e628 100644 --- a/src/Avalonia.Controls/Primitives/TabStrip.cs +++ b/src/Avalonia.Controls/Primitives/TabStrip.cs @@ -12,11 +12,8 @@ namespace Avalonia.Controls.Primitives private static readonly FuncTemplate DefaultPanel = new FuncTemplate(() => new WrapPanel { Orientation = Orientation.Horizontal }); - private static IMemberSelector s_MemberSelector = new FuncMemberSelector(SelectHeader); - static TabStrip() { - MemberSelectorProperty.OverrideDefaultValue(s_MemberSelector); SelectionModeProperty.OverrideDefaultValue(SelectionMode.AlwaysSelected); FocusableProperty.OverrideDefaultValue(typeof(TabStrip), false); ItemsPanelProperty.OverrideDefaultValue(DefaultPanel); @@ -51,11 +48,5 @@ namespace Avalonia.Controls.Primitives e.Handled = UpdateSelectionFromEventSource(e.Source); } } - - private static object SelectHeader(object o) - { - var headered = o as IHeadered; - return (headered != null) ? (headered.Header ?? string.Empty) : o; - } } } diff --git a/src/Avalonia.Controls/Templates/FuncMemberSelector.cs b/src/Avalonia.Controls/Templates/FuncMemberSelector.cs deleted file mode 100644 index 5ab186261e..0000000000 --- a/src/Avalonia.Controls/Templates/FuncMemberSelector.cs +++ /dev/null @@ -1,35 +0,0 @@ -// 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; - -namespace Avalonia.Controls.Templates -{ - /// - /// Selects a member of an object using a . - /// - public class FuncMemberSelector : IMemberSelector - { - private readonly Func _selector; - - /// - /// Initializes a new instance of the - /// class. - /// - /// The selector. - public FuncMemberSelector(Func selector) - { - this._selector = selector; - } - - /// - /// Selects a member of an object. - /// - /// The object. - /// The selected member. - public object Select(object o) - { - return (o is TObject) ? _selector((TObject)o) : default(TMember); - } - } -} diff --git a/src/Avalonia.Controls/Templates/IMemberSelector.cs b/src/Avalonia.Controls/Templates/IMemberSelector.cs deleted file mode 100644 index e1ec42a849..0000000000 --- a/src/Avalonia.Controls/Templates/IMemberSelector.cs +++ /dev/null @@ -1,18 +0,0 @@ -// 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. - -namespace Avalonia.Controls.Templates -{ - /// - /// Selects a member of an object. - /// - public interface IMemberSelector - { - /// - /// Selects a member of an object. - /// - /// The object. - /// The selected member. - object Select(object o); - } -} diff --git a/src/Avalonia.Themes.Default/AutoCompleteBox.xaml b/src/Avalonia.Themes.Default/AutoCompleteBox.xaml index 11d8a344d9..788b60892b 100644 --- a/src/Avalonia.Themes.Default/AutoCompleteBox.xaml +++ b/src/Avalonia.Themes.Default/AutoCompleteBox.xaml @@ -27,7 +27,6 @@ Background="{TemplateBinding Background}" Foreground="{TemplateBinding Foreground}" ItemTemplate="{TemplateBinding ItemTemplate}" - MemberSelector="{TemplateBinding ValueMemberSelector}" ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Auto" /> diff --git a/src/Avalonia.Themes.Default/Carousel.xaml b/src/Avalonia.Themes.Default/Carousel.xaml index efe12c4333..955a49a974 100644 --- a/src/Avalonia.Themes.Default/Carousel.xaml +++ b/src/Avalonia.Themes.Default/Carousel.xaml @@ -8,10 +8,9 @@ Items="{TemplateBinding Items}" ItemsPanel="{TemplateBinding ItemsPanel}" Margin="{TemplateBinding Padding}" - MemberSelector="{TemplateBinding MemberSelector}" SelectedIndex="{TemplateBinding SelectedIndex}" PageTransition="{TemplateBinding PageTransition}"/> - \ No newline at end of file + diff --git a/src/Avalonia.Themes.Default/ComboBox.xaml b/src/Avalonia.Themes.Default/ComboBox.xaml index ca6c2e372e..6227962a48 100644 --- a/src/Avalonia.Themes.Default/ComboBox.xaml +++ b/src/Avalonia.Themes.Default/ComboBox.xaml @@ -45,7 +45,6 @@ Items="{TemplateBinding Items}" ItemsPanel="{TemplateBinding ItemsPanel}" ItemTemplate="{TemplateBinding ItemTemplate}" - MemberSelector="{TemplateBinding MemberSelector}" VirtualizationMode="{TemplateBinding VirtualizationMode}" /> diff --git a/src/Avalonia.Themes.Default/DataValidationErrors.xaml b/src/Avalonia.Themes.Default/DataValidationErrors.xaml index 0c40a7eb25..f4145a51f5 100644 --- a/src/Avalonia.Themes.Default/DataValidationErrors.xaml +++ b/src/Avalonia.Themes.Default/DataValidationErrors.xaml @@ -29,7 +29,7 @@ - + diff --git a/src/Avalonia.Themes.Default/ItemsControl.xaml b/src/Avalonia.Themes.Default/ItemsControl.xaml index 7b6671b42c..f3def542fc 100644 --- a/src/Avalonia.Themes.Default/ItemsControl.xaml +++ b/src/Avalonia.Themes.Default/ItemsControl.xaml @@ -4,8 +4,7 @@ + ItemTemplate="{TemplateBinding ItemTemplate}"/> - \ No newline at end of file + diff --git a/src/Avalonia.Themes.Default/ListBox.xaml b/src/Avalonia.Themes.Default/ListBox.xaml index 57b0c541b8..59c596bcaa 100644 --- a/src/Avalonia.Themes.Default/ListBox.xaml +++ b/src/Avalonia.Themes.Default/ListBox.xaml @@ -18,10 +18,9 @@ ItemsPanel="{TemplateBinding ItemsPanel}" ItemTemplate="{TemplateBinding ItemTemplate}" Margin="{TemplateBinding Padding}" - MemberSelector="{TemplateBinding MemberSelector}" VirtualizationMode="{TemplateBinding VirtualizationMode}"/> - \ No newline at end of file + diff --git a/src/Avalonia.Themes.Default/MenuItem.xaml b/src/Avalonia.Themes.Default/MenuItem.xaml index be86e8b14c..a794d15577 100644 --- a/src/Avalonia.Themes.Default/MenuItem.xaml +++ b/src/Avalonia.Themes.Default/MenuItem.xaml @@ -56,8 +56,7 @@ Items="{TemplateBinding Items}" ItemsPanel="{TemplateBinding ItemsPanel}" ItemTemplate="{TemplateBinding ItemTemplate}" - Margin="2" - MemberSelector="{TemplateBinding MemberSelector}"/> + Margin="2"/> + Margin="2"/> + ItemTemplate="{TemplateBinding ItemTemplate}"> @@ -18,4 +17,4 @@ - \ No newline at end of file + diff --git a/src/Avalonia.Themes.Default/TreeView.xaml b/src/Avalonia.Themes.Default/TreeView.xaml index 4e38c6db3a..6ed2fd17b8 100644 --- a/src/Avalonia.Themes.Default/TreeView.xaml +++ b/src/Avalonia.Themes.Default/TreeView.xaml @@ -15,8 +15,7 @@ + Margin="{TemplateBinding Padding}"/> diff --git a/src/Avalonia.Themes.Default/TreeViewItem.xaml b/src/Avalonia.Themes.Default/TreeViewItem.xaml index b5e0e7a005..5dd082cf7a 100644 --- a/src/Avalonia.Themes.Default/TreeViewItem.xaml +++ b/src/Avalonia.Themes.Default/TreeViewItem.xaml @@ -32,8 +32,7 @@ + ItemsPanel="{TemplateBinding ItemsPanel}"/> diff --git a/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj b/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj index 6f3dabd568..06c5375520 100644 --- a/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj +++ b/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj @@ -12,7 +12,6 @@ - @@ -33,7 +32,6 @@ - diff --git a/src/Markup/Avalonia.Markup.Xaml/Converters/MemberSelectorTypeConverter.cs b/src/Markup/Avalonia.Markup.Xaml/Converters/MemberSelectorTypeConverter.cs deleted file mode 100644 index 8dc052fe63..0000000000 --- a/src/Markup/Avalonia.Markup.Xaml/Converters/MemberSelectorTypeConverter.cs +++ /dev/null @@ -1,24 +0,0 @@ -// 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.Globalization; -using Avalonia.Markup.Xaml.Templates; - -namespace Avalonia.Markup.Xaml.Converters -{ - using System.ComponentModel; - - public class MemberSelectorTypeConverter : TypeConverter - { - public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) - { - return sourceType == typeof(string); - } - - public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) - { - return MemberSelector.Parse((string)value); - } - } -} \ No newline at end of file diff --git a/src/Markup/Avalonia.Markup.Xaml/Templates/MemberSelector.cs b/src/Markup/Avalonia.Markup.Xaml/Templates/MemberSelector.cs deleted file mode 100644 index fa91ab60ff..0000000000 --- a/src/Markup/Avalonia.Markup.Xaml/Templates/MemberSelector.cs +++ /dev/null @@ -1,48 +0,0 @@ -// 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 Avalonia.Controls.Templates; -using Avalonia.Data; -using Avalonia.Data.Core; -using Avalonia.Markup.Parsers; -using System; -using System.Reactive.Linq; - -namespace Avalonia.Markup.Xaml.Templates -{ - public class MemberSelector : IMemberSelector - { - private string _memberName; - - public string MemberName - { - get { return _memberName; } - set - { - if (_memberName != value) - { - _memberName = value; - } - } - } - - public static MemberSelector Parse(string s) - { - return new MemberSelector { MemberName = s }; - } - - public object Select(object o) - { - if (string.IsNullOrEmpty(MemberName)) - { - return o; - } - - var expression = ExpressionObserverBuilder.Build(o, MemberName); - object result = AvaloniaProperty.UnsetValue; - - expression.Subscribe(x => result = x); - return (result == AvaloniaProperty.UnsetValue || result is BindingNotification) ? null : result; - } - } -} \ No newline at end of file diff --git a/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/AvaloniaXamlIlLanguage.cs b/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/AvaloniaXamlIlLanguage.cs index c25e1186d0..830e354274 100644 --- a/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/AvaloniaXamlIlLanguage.cs +++ b/src/Markup/Avalonia.Markup.Xaml/XamlIl/CompilerExtensions/AvaloniaXamlIlLanguage.cs @@ -81,8 +81,6 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions var ilist = typeSystem.GetType("System.Collections.Generic.IList`1"); AddType(ilist.MakeGenericType(typeSystem.GetType("Avalonia.Point")), typeSystem.GetType("Avalonia.Markup.Xaml.Converters.PointsListTypeConverter")); - Add("Avalonia.Controls.Templates.IMemberSelector", - "Avalonia.Markup.Xaml.Converters.MemberSelectorTypeConverter"); Add("Avalonia.Controls.WindowIcon","Avalonia.Markup.Xaml.Converters.IconTypeConverter"); Add("System.Globalization.CultureInfo", "System.ComponentModel.CultureInfoConverter"); Add("System.Uri", "Avalonia.Markup.Xaml.Converters.AvaloniaUriTypeConverter"); diff --git a/tests/Avalonia.Controls.UnitTests/Generators/ItemContainerGeneratorTests.cs b/tests/Avalonia.Controls.UnitTests/Generators/ItemContainerGeneratorTests.cs index 9b4be59647..70410dff0d 100644 --- a/tests/Avalonia.Controls.UnitTests/Generators/ItemContainerGeneratorTests.cs +++ b/tests/Avalonia.Controls.UnitTests/Generators/ItemContainerGeneratorTests.cs @@ -118,7 +118,7 @@ namespace Avalonia.Controls.UnitTests.Generators { var owner = new Decorator(); var target = new ItemContainerGenerator(owner); - var container = (ContentPresenter)target.Materialize(0, "foo", null).ContainerControl; + var container = (ContentPresenter)target.Materialize(0, "foo").ContainerControl; Assert.Equal("foo", container.Content); @@ -135,7 +135,7 @@ namespace Avalonia.Controls.UnitTests.Generators { var owner = new Decorator(); var target = new ItemContainerGenerator(owner, ListBoxItem.ContentProperty, null); - var container = (ListBoxItem)target.Materialize(0, "foo", null).ContainerControl; + var container = (ListBoxItem)target.Materialize(0, "foo").ContainerControl; Assert.Equal("foo", container.Content); @@ -156,7 +156,7 @@ namespace Avalonia.Controls.UnitTests.Generators foreach (var item in items) { - var container = generator.Materialize(index++, item, null); + var container = generator.Materialize(index++, item); result.Add(container); } diff --git a/tests/Avalonia.Controls.UnitTests/Generators/ItemContainerGeneratorTypedTests.cs b/tests/Avalonia.Controls.UnitTests/Generators/ItemContainerGeneratorTypedTests.cs index f63c0efbf9..05954cbcd2 100644 --- a/tests/Avalonia.Controls.UnitTests/Generators/ItemContainerGeneratorTypedTests.cs +++ b/tests/Avalonia.Controls.UnitTests/Generators/ItemContainerGeneratorTypedTests.cs @@ -35,7 +35,7 @@ namespace Avalonia.Controls.UnitTests.Generators foreach (var item in items) { - var container = generator.Materialize(index++, item, null); + var container = generator.Materialize(index++, item); result.Add(container); } diff --git a/tests/Avalonia.Controls.UnitTests/ItemsControlTests.cs b/tests/Avalonia.Controls.UnitTests/ItemsControlTests.cs index 3cf886ade4..ca945c66bf 100644 --- a/tests/Avalonia.Controls.UnitTests/ItemsControlTests.cs +++ b/tests/Avalonia.Controls.UnitTests/ItemsControlTests.cs @@ -430,27 +430,6 @@ namespace Avalonia.Controls.UnitTests dataContexts); } - [Fact] - public void MemberSelector_Should_Select_Member() - { - var target = new ItemsControl - { - Template = GetTemplate(), - Items = new[] { new Item("Foo"), new Item("Bar") }, - MemberSelector = new FuncMemberSelector(x => x.Value), - }; - - target.ApplyTemplate(); - target.Presenter.ApplyTemplate(); - - var text = target.Presenter.Panel.Children - .Cast() - .Select(x => x.Content) - .ToList(); - - Assert.Equal(new[] { "Foo", "Bar" }, text); - } - [Fact] public void Control_Item_Should_Not_Be_NameScope() { @@ -586,7 +565,6 @@ namespace Avalonia.Controls.UnitTests Child = new ItemsPresenter { Name = "PART_ItemsPresenter", - MemberSelector = parent.MemberSelector, [~ItemsPresenter.ItemsProperty] = parent[~ItemsControl.ItemsProperty], } }; diff --git a/tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests.cs b/tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests.cs index 3d13e4c32f..0c9d36ba3a 100644 --- a/tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests.cs +++ b/tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests.cs @@ -310,46 +310,6 @@ namespace Avalonia.Controls.UnitTests.Presenters Assert.Equal(target.Panel, child); } - [Fact] - public void MemberSelector_Should_Select_Member() - { - var target = new ItemsPresenter - { - Items = new[] { new Item("Foo"), new Item("Bar") }, - MemberSelector = new FuncMemberSelector(x => x.Value), - }; - - target.ApplyTemplate(); - - var text = target.Panel.Children - .Cast() - .Select(x => x.Content) - .ToList(); - - Assert.Equal(new[] { "Foo", "Bar" }, text); - } - - [Fact] - public void MemberSelector_Should_Set_DataContext() - { - var items = new[] { new Item("Foo"), new Item("Bar") }; - var target = new ItemsPresenter - { - Items = items, - MemberSelector = new FuncMemberSelector(x => x.Value), - }; - - target.ApplyTemplate(); - - var dataContexts = target.Panel.Children - .Cast() - .Do(x => x.UpdateChild()) - .Select(x => x.DataContext) - .ToList(); - - Assert.Equal(new[] { "Foo", "Bar" }, dataContexts); - } - private class Item { public Item(string value) diff --git a/tests/Avalonia.Controls.UnitTests/Primitives/TabStripTests.cs b/tests/Avalonia.Controls.UnitTests/Primitives/TabStripTests.cs index 55b3d6f756..622169f8f6 100644 --- a/tests/Avalonia.Controls.UnitTests/Primitives/TabStripTests.cs +++ b/tests/Avalonia.Controls.UnitTests/Primitives/TabStripTests.cs @@ -14,60 +14,6 @@ namespace Avalonia.Controls.UnitTests.Primitives { public class TabStripTests { - [Fact] - public void Header_Of_IHeadered_Items_Should_Be_Used() - { - var items = new[] - { -#pragma warning disable CS0252 // Possible unintended reference comparison; left hand side needs cast - Mock.Of(x => x.Header == "foo"), - Mock.Of(x => x.Header == "bar"), -#pragma warning restore CS0252 // Possible unintended reference comparison; left hand side needs cast - }; - - var target = new TabStrip - { - Template = new FuncControlTemplate(CreateTabStripTemplate), - Items = items, - }; - - target.ApplyTemplate(); - target.Presenter.ApplyTemplate(); - - var result = target.GetLogicalChildren() - .OfType() - .Select(x => x.Content) - .ToList(); - - Assert.Equal(new[] { "foo", "bar" }, result); - } - - [Fact] - public void Data_Of_Non_IHeadered_Items_Should_Be_Used() - { - var items = new[] - { - "foo", - "bar" - }; - - var target = new TabStrip - { - Template = new FuncControlTemplate(CreateTabStripTemplate), - Items = items, - }; - - target.ApplyTemplate(); - target.Presenter.ApplyTemplate(); - - var result = target.GetLogicalChildren() - .OfType() - .Select(x => x.Content) - .ToList(); - - Assert.Equal(new[] { "foo", "bar" }, result); - } - [Fact] public void First_Tab_Should_Be_Selected_By_Default() { @@ -165,7 +111,6 @@ namespace Avalonia.Controls.UnitTests.Primitives { Name = "itemsPresenter", [!ItemsPresenter.ItemsProperty] = parent[!ItemsControl.ItemsProperty], - [!ItemsPresenter.MemberSelectorProperty] = parent[!ItemsControl.MemberSelectorProperty], }; } } diff --git a/tests/Avalonia.LeakTests/MemberSelectorTests.cs b/tests/Avalonia.LeakTests/MemberSelectorTests.cs deleted file mode 100644 index ffee18ae0a..0000000000 --- a/tests/Avalonia.LeakTests/MemberSelectorTests.cs +++ /dev/null @@ -1,55 +0,0 @@ -using Avalonia.Markup.Xaml.Templates; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using JetBrains.dotMemoryUnit; -using Xunit; -using Xunit.Abstractions; - -namespace Avalonia.LeakTests -{ - [DotMemoryUnit(FailIfRunWithoutSupport = false)] - public class MemberSelectorTests - { - public MemberSelectorTests(ITestOutputHelper atr) - { - DotMemoryUnitTestOutput.SetOutputMethod(atr.WriteLine); - } - - [Fact] - public void Should_Not_Hold_Reference_To_Object() - { - WeakReference dataRef = null; - - var selector = new MemberSelector() { MemberName = "Child.StringValue" }; - - Action run = () => - { - var data = new Item() - { - Child = new Item() { StringValue = "Value1" } - }; - - Assert.Same("Value1", selector.Select(data)); - - dataRef = new WeakReference(data); - }; - - run(); - - GC.Collect(); - - Assert.False(dataRef.IsAlive); - } - - private class Item - { - public Item Child { get; set; } - public int IntValue { get; set; } - - public string StringValue { get; set; } - } - } -} diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/Templates/MemberSelectorTests.cs b/tests/Avalonia.Markup.Xaml.UnitTests/Templates/MemberSelectorTests.cs deleted file mode 100644 index aa1e56f2a5..0000000000 --- a/tests/Avalonia.Markup.Xaml.UnitTests/Templates/MemberSelectorTests.cs +++ /dev/null @@ -1,159 +0,0 @@ -// 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 Avalonia.Markup.Xaml.Templates; -using System; -using Xunit; - -namespace Avalonia.Markup.Xaml.UnitTests.Templates -{ - public class MemberSelectorTests - { - [Fact] - public void Should_Select_Child_Property_Value() - { - var selector = new MemberSelector() { MemberName = "Child.StringValue" }; - - var data = new Item() - { - Child = new Item() { StringValue = "Value1" } - }; - - Assert.Same("Value1", selector.Select(data)); - } - - [Fact] - public void Should_Select_Child_Property_Value_In_Multiple_Items() - { - var selector = new MemberSelector() { MemberName = "Child.StringValue" }; - - var data = new Item[] - { - new Item() { Child = new Item() { StringValue = "Value1" } }, - new Item() { Child = new Item() { StringValue = "Value2" } }, - new Item() { Child = new Item() { StringValue = "Value3" } } - }; - - Assert.Same("Value1", selector.Select(data[0])); - Assert.Same("Value2", selector.Select(data[1])); - Assert.Same("Value3", selector.Select(data[2])); - } - - [Fact] - public void Should_Select_MoreComplex_Property_Value() - { - var selector = new MemberSelector() { MemberName = "Child.Child.Child.StringValue" }; - - var data = new Item() - { - Child = new Item() - { - Child = new Item() - { - Child = new Item() { StringValue = "Value1" } - } - } - }; - - Assert.Same("Value1", selector.Select(data)); - } - - [Fact] - public void Should_Select_Null_Value_On_Null_Object() - { - var selector = new MemberSelector() { MemberName = "StringValue" }; - - Assert.Null(selector.Select(null)); - } - - [Fact] - public void Should_Select_Null_Value_On_Wrong_MemberName() - { - var selector = new MemberSelector() { MemberName = "WrongProperty" }; - - var data = new Item() { StringValue = "Value1" }; - - Assert.Null(selector.Select(data)); - } - - [Fact] - public void Should_Select_Simple_Property_Value() - { - var selector = new MemberSelector() { MemberName = "StringValue" }; - - var data = new Item() { StringValue = "Value1" }; - - Assert.Same("Value1", selector.Select(data)); - } - - [Fact] - public void Should_Select_Simple_Property_Value_In_Multiple_Items() - { - var selector = new MemberSelector() { MemberName = "StringValue" }; - - var data = new Item[] - { - new Item() { StringValue = "Value1" }, - new Item() { StringValue = "Value2" }, - new Item() { StringValue = "Value3" } - }; - - Assert.Same("Value1", selector.Select(data[0])); - Assert.Same("Value2", selector.Select(data[1])); - Assert.Same("Value3", selector.Select(data[2])); - } - - [Fact] - public void Should_Select_Target_On_Empty_MemberName() - { - var selector = new MemberSelector(); - - var data = new Item() { StringValue = "Value1" }; - - Assert.Same(data, selector.Select(data)); - } - - [Fact] - public void Should_Support_Change_Of_MemberName() - { - var selector = new MemberSelector() { MemberName = "StringValue" }; - - var data = new Item() - { - StringValue = "Value1", - IntValue = 1 - }; - - Assert.Same("Value1", selector.Select(data)); - - selector.MemberName = "IntValue"; - - Assert.Equal(1, selector.Select(data)); - } - - [Fact] - public void Should_Support_Change_Of_Target_Value() - { - var selector = new MemberSelector() { MemberName = "StringValue" }; - - var data = new Item() - { - StringValue = "Value1" - }; - - Assert.Same("Value1", selector.Select(data)); - - data.StringValue = "Value2"; - - Assert.Same("Value2", selector.Select(data)); - } - - private class Item - { - public Item Child { get; set; } - public int IntValue { get; set; } - - public string StringValue { get; set; } - } - } -} \ No newline at end of file diff --git a/tests/Avalonia.ReactiveUI.UnitTests/AutoDataTemplateBindingHookTest.cs b/tests/Avalonia.ReactiveUI.UnitTests/AutoDataTemplateBindingHookTest.cs index 667462eb91..b8fd7d166d 100644 --- a/tests/Avalonia.ReactiveUI.UnitTests/AutoDataTemplateBindingHookTest.cs +++ b/tests/Avalonia.ReactiveUI.UnitTests/AutoDataTemplateBindingHookTest.cs @@ -106,11 +106,10 @@ namespace Avalonia.ReactiveUI.UnitTests Child = new ItemsPresenter { Name = "PART_ItemsPresenter", - MemberSelector = parent.MemberSelector, [~ItemsPresenter.ItemsProperty] = parent[~ItemsControl.ItemsProperty], } }; }); } } -} \ No newline at end of file +} From 139475de1c26323c62ddef0f2031c4a7094a7c95 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Thu, 27 Jun 2019 11:23:11 +0200 Subject: [PATCH 2/2] Added TabStripPage to ControlCatalog. To make sure that everything still works with TabStrip. --- samples/ControlCatalog/MainView.xaml | 1 + .../ControlCatalog/Pages/TabStripPage.xaml | 33 ++++++++++++++ .../ControlCatalog/Pages/TabStripPage.xaml.cs | 45 +++++++++++++++++++ 3 files changed, 79 insertions(+) create mode 100644 samples/ControlCatalog/Pages/TabStripPage.xaml create mode 100644 samples/ControlCatalog/Pages/TabStripPage.xaml.cs diff --git a/samples/ControlCatalog/MainView.xaml b/samples/ControlCatalog/MainView.xaml index 1cddb9d295..8699508320 100644 --- a/samples/ControlCatalog/MainView.xaml +++ b/samples/ControlCatalog/MainView.xaml @@ -36,6 +36,7 @@ + diff --git a/samples/ControlCatalog/Pages/TabStripPage.xaml b/samples/ControlCatalog/Pages/TabStripPage.xaml new file mode 100644 index 0000000000..a824336f75 --- /dev/null +++ b/samples/ControlCatalog/Pages/TabStripPage.xaml @@ -0,0 +1,33 @@ + + + TabStrip + A control which displays a selectable strip of tabs + + + + Defined in XAML + + Item 1 + Item 2 + Disabled + + + + + Dynamically generated + + + + + + + + + + + + diff --git a/samples/ControlCatalog/Pages/TabStripPage.xaml.cs b/samples/ControlCatalog/Pages/TabStripPage.xaml.cs new file mode 100644 index 0000000000..f0630cf534 --- /dev/null +++ b/samples/ControlCatalog/Pages/TabStripPage.xaml.cs @@ -0,0 +1,45 @@ +using System; +using Avalonia; +using Avalonia.Controls; +using Avalonia.Markup.Xaml; +using Avalonia.Media.Imaging; +using Avalonia.Platform; + +namespace ControlCatalog.Pages +{ + public class TabStripPage : UserControl + { + public TabStripPage() + { + InitializeComponent(); + + DataContext = new[] + { + new TabStripItemViewModel + { + Header = "Item 1", + }, + new TabStripItemViewModel + { + Header = "Item 2", + }, + new TabStripItemViewModel + { + Header = "Disabled", + IsEnabled = false, + }, + }; + } + + private void InitializeComponent() + { + AvaloniaXamlLoader.Load(this); + } + + private class TabStripItemViewModel + { + public string Header { get; set; } + public bool IsEnabled { get; set; } = true; + } + } +}