diff --git a/.ncrunch/SafeAreaDemo.Android.v3.ncrunchproject b/.ncrunch/SafeAreaDemo.Android.v3.ncrunchproject new file mode 100644 index 0000000000..319cd523ce --- /dev/null +++ b/.ncrunch/SafeAreaDemo.Android.v3.ncrunchproject @@ -0,0 +1,5 @@ + + + True + + \ No newline at end of file diff --git a/.ncrunch/SafeAreaDemo.Desktop.v3.ncrunchproject b/.ncrunch/SafeAreaDemo.Desktop.v3.ncrunchproject new file mode 100644 index 0000000000..319cd523ce --- /dev/null +++ b/.ncrunch/SafeAreaDemo.Desktop.v3.ncrunchproject @@ -0,0 +1,5 @@ + + + True + + \ No newline at end of file diff --git a/.ncrunch/SafeAreaDemo.iOS.v3.ncrunchproject b/.ncrunch/SafeAreaDemo.iOS.v3.ncrunchproject new file mode 100644 index 0000000000..319cd523ce --- /dev/null +++ b/.ncrunch/SafeAreaDemo.iOS.v3.ncrunchproject @@ -0,0 +1,5 @@ + + + True + + \ No newline at end of file diff --git a/.ncrunch/SafeAreaDemo.v3.ncrunchproject b/.ncrunch/SafeAreaDemo.v3.ncrunchproject new file mode 100644 index 0000000000..319cd523ce --- /dev/null +++ b/.ncrunch/SafeAreaDemo.v3.ncrunchproject @@ -0,0 +1,5 @@ + + + True + + \ No newline at end of file diff --git a/samples/ControlCatalog/Pages/AutoCompleteBoxPage.xaml.cs b/samples/ControlCatalog/Pages/AutoCompleteBoxPage.xaml.cs index ae7e43f511..81d379ce05 100644 --- a/samples/ControlCatalog/Pages/AutoCompleteBoxPage.xaml.cs +++ b/samples/ControlCatalog/Pages/AutoCompleteBoxPage.xaml.cs @@ -114,7 +114,7 @@ namespace ControlCatalog.Pages foreach (AutoCompleteBox box in GetAllAutoCompleteBox().Where(x => x.Name != "CustomAutocompleteBox")) { - box.Items = States; + box.ItemsSource = States; } var converter = new FuncMultiValueConverter(parts => @@ -132,7 +132,7 @@ namespace ControlCatalog.Pages asyncBox.AsyncPopulator = PopulateAsync; var customAutocompleteBox = this.Get("CustomAutocompleteBox"); - customAutocompleteBox.Items = Sentences.SelectMany(x => x); + customAutocompleteBox.ItemsSource = Sentences.SelectMany(x => x); customAutocompleteBox.TextFilter = LastWordContains; customAutocompleteBox.TextSelector = AppendWord; } diff --git a/samples/ControlCatalog/Pages/ContextFlyoutPage.xaml b/samples/ControlCatalog/Pages/ContextFlyoutPage.xaml index cb294442d2..56f8547740 100644 --- a/samples/ControlCatalog/Pages/ContextFlyoutPage.xaml +++ b/samples/ControlCatalog/Pages/ContextFlyoutPage.xaml @@ -67,7 +67,7 @@ - + diff --git a/samples/ControlCatalog/Pages/DataGridPage.xaml b/samples/ControlCatalog/Pages/DataGridPage.xaml index c39e9f0a81..fb097da71b 100644 --- a/samples/ControlCatalog/Pages/DataGridPage.xaml +++ b/samples/ControlCatalog/Pages/DataGridPage.xaml @@ -94,7 +94,7 @@ + ItemsSource="{Binding DataGrid3Source}"> diff --git a/samples/ControlCatalog/Pages/DataGridPage.xaml.cs b/samples/ControlCatalog/Pages/DataGridPage.xaml.cs index b0c3e3a553..617b0db5ed 100644 --- a/samples/ControlCatalog/Pages/DataGridPage.xaml.cs +++ b/samples/ControlCatalog/Pages/DataGridPage.xaml.cs @@ -36,7 +36,7 @@ namespace ControlCatalog.Pages collectionView1.SortDescriptions.Add(dataGridSortDescription); } }; - dg1.Items = collectionView1; + dg1.ItemsSource = collectionView1; var dg2 = this.Get("dataGridGrouping"); dg2.IsReadOnly = true; @@ -44,7 +44,7 @@ namespace ControlCatalog.Pages var collectionView2 = new DataGridCollectionView(Countries.All); collectionView2.GroupDescriptions.Add(new DataGridPathGroupDescription("Region")); - dg2.Items = collectionView2; + dg2.ItemsSource = collectionView2; var dg3 = this.Get("dataGridEdit"); dg3.IsReadOnly = false; diff --git a/samples/ControlCatalog/Pages/DialogsPage.xaml b/samples/ControlCatalog/Pages/DialogsPage.xaml index 90c717e7ed..980b210aaa 100644 --- a/samples/ControlCatalog/Pages/DialogsPage.xaml +++ b/samples/ControlCatalog/Pages/DialogsPage.xaml @@ -45,7 +45,7 @@ - + Desktop Documents @@ -54,7 +54,7 @@ Videos Music - + - diff --git a/src/Avalonia.Controls.DataGrid/DataGrid.cs b/src/Avalonia.Controls.DataGrid/DataGrid.cs index 030776ba14..e56e32a5ff 100644 --- a/src/Avalonia.Controls.DataGrid/DataGrid.cs +++ b/src/Avalonia.Controls.DataGrid/DataGrid.cs @@ -152,8 +152,6 @@ namespace Avalonia.Controls private double _verticalOffset; private byte _verticalScrollChangesIgnored; - private IEnumerable _items; - public event EventHandler HorizontalScroll; public event EventHandler VerticalScroll; @@ -652,21 +650,18 @@ namespace Avalonia.Controls } /// - /// Identifies the ItemsSource dependency property. + /// Identifies the ItemsSource property. /// - public static readonly DirectProperty ItemsProperty = - AvaloniaProperty.RegisterDirect( - nameof(Items), - o => o.Items, - (o, v) => o.Items = v); + public static readonly StyledProperty ItemsSourceProperty = + AvaloniaProperty.Register(nameof(ItemsSource)); /// /// Gets or sets a collection that is used to generate the content of the control. /// - public IEnumerable Items + public IEnumerable ItemsSource { - get { return _items; } - set { SetAndRaise(ItemsProperty, ref _items, value); } + get => GetValue(ItemsSourceProperty); + set => SetValue(ItemsSourceProperty, value); } public static readonly StyledProperty AreRowDetailsFrozenProperty = @@ -713,7 +708,7 @@ namespace Avalonia.Controls HorizontalScrollBarVisibilityProperty, VerticalScrollBarVisibilityProperty); - ItemsProperty.Changed.AddClassHandler((x, e) => x.OnItemsPropertyChanged(e)); + ItemsSourceProperty.Changed.AddClassHandler((x, e) => x.OnItemsSourcePropertyChanged(e)); CanUserResizeColumnsProperty.Changed.AddClassHandler((x, e) => x.OnCanUserResizeColumnsChanged(e)); ColumnWidthProperty.Changed.AddClassHandler((x, e) => x.OnColumnWidthChanged(e)); FrozenColumnCountProperty.Changed.AddClassHandler((x, e) => x.OnFrozenColumnCountChanged(e)); @@ -816,10 +811,10 @@ namespace Avalonia.Controls } /// - /// ItemsProperty property changed handler. + /// ItemsSourceProperty property changed handler. /// /// The event arguments. - private void OnItemsPropertyChanged(AvaloniaPropertyChangedEventArgs e) + private void OnItemsSourcePropertyChanged(AvaloniaPropertyChangedEventArgs e) { if (!_areHandlersSuspended) { @@ -830,7 +825,7 @@ namespace Avalonia.Controls if (LoadingOrUnloadingRow) { - SetValueNoCallback(ItemsProperty, oldValue); + SetValueNoCallback(ItemsSourceProperty, oldValue); throw DataGridError.DataGrid.CannotChangeItemsWhenLoadingRows(); } @@ -1855,7 +1850,7 @@ namespace Avalonia.Controls { get { - if (CurrentSlot == -1 || Items == null || RowGroupHeadersTable.Contains(CurrentSlot)) + if (CurrentSlot == -1 || ItemsSource == null || RowGroupHeadersTable.Contains(CurrentSlot)) { return null; } diff --git a/src/Avalonia.Controls.DataGrid/DataGridBoundColumn.cs b/src/Avalonia.Controls.DataGrid/DataGridBoundColumn.cs index 110590fef2..61a1eb2bf0 100644 --- a/src/Avalonia.Controls.DataGrid/DataGridBoundColumn.cs +++ b/src/Avalonia.Controls.DataGrid/DataGridBoundColumn.cs @@ -25,7 +25,7 @@ namespace Avalonia.Controls /// //TODO Binding [AssignBinding] - [InheritDataTypeFromItems(nameof(DataGrid.Items), AncestorType = typeof(DataGrid))] + [InheritDataTypeFromItems(nameof(DataGrid.ItemsSource), AncestorType = typeof(DataGrid))] public virtual IBinding Binding { get diff --git a/src/Avalonia.Controls.DataGrid/DataGridDataConnection.cs b/src/Avalonia.Controls.DataGrid/DataGridDataConnection.cs index ae52e5f970..ee9cc04420 100644 --- a/src/Avalonia.Controls.DataGrid/DataGridDataConnection.cs +++ b/src/Avalonia.Controls.DataGrid/DataGridDataConnection.cs @@ -122,9 +122,9 @@ namespace Avalonia.Controls // We need to use the raw ItemsSource as opposed to DataSource because DataSource // may be the ItemsSource wrapped in a collection view, in which case we wouldn't // be able to take T to be the type if we're given IEnumerable - if (_dataType == null && _owner.Items != null) + if (_dataType == null && _owner.ItemsSource != null) { - _dataType = _owner.Items.GetItemType(); + _dataType = _owner.ItemsSource.GetItemType(); } return _dataType; } diff --git a/src/Avalonia.Controls.DataGrid/DataGridTemplateColumn.cs b/src/Avalonia.Controls.DataGrid/DataGridTemplateColumn.cs index 00318e2dd8..0bfb4b6913 100644 --- a/src/Avalonia.Controls.DataGrid/DataGridTemplateColumn.cs +++ b/src/Avalonia.Controls.DataGrid/DataGridTemplateColumn.cs @@ -24,7 +24,7 @@ namespace Avalonia.Controls (o, v) => o.CellTemplate = v); [Content] - [InheritDataTypeFromItems(nameof(DataGrid.Items), AncestorType = typeof(DataGrid))] + [InheritDataTypeFromItems(nameof(DataGrid.ItemsSource), AncestorType = typeof(DataGrid))] public IDataTemplate CellTemplate { get { return _cellTemplate; } @@ -51,7 +51,7 @@ namespace Avalonia.Controls /// /// If this property is the column is read-only. /// - [InheritDataTypeFromItems(nameof(DataGrid.Items), AncestorType = typeof(DataGrid))] + [InheritDataTypeFromItems(nameof(DataGrid.ItemsSource), AncestorType = typeof(DataGrid))] public IDataTemplate CellEditingTemplate { get => _cellEditingCellTemplate; diff --git a/src/Avalonia.Controls.ItemsRepeater/Controls/ItemsRepeater.cs b/src/Avalonia.Controls.ItemsRepeater/Controls/ItemsRepeater.cs index 499904deac..5fe9c6fa05 100644 --- a/src/Avalonia.Controls.ItemsRepeater/Controls/ItemsRepeater.cs +++ b/src/Avalonia.Controls.ItemsRepeater/Controls/ItemsRepeater.cs @@ -36,13 +36,13 @@ namespace Avalonia.Controls ItemsControl.ItemTemplateProperty.AddOwner(); /// - /// Defines the property. + /// Defines the property. /// - public static readonly DirectProperty ItemsProperty = + public static readonly DirectProperty ItemsSourceProperty = AvaloniaProperty.RegisterDirect( - nameof(Items), - o => o.Items, - (o, v) => o.Items = v); + nameof(ItemsSource), + o => o.ItemsSource, + (o, v) => o.ItemsSource = v); /// /// Defines the property. @@ -65,7 +65,7 @@ namespace Avalonia.Controls private readonly ViewManager _viewManager; private readonly ViewportManager _viewportManager; private readonly TargetWeakEventSubscriber _layoutWeakSubscriber; - private IEnumerable? _items; + private IEnumerable? _itemsSource; private RepeaterLayoutContext? _layoutContext; private EventHandler? _childIndexChanged; private bool _isLayoutInProgress; @@ -116,16 +116,16 @@ namespace Avalonia.Controls /// /// Gets or sets an object source used to generate the content of the ItemsRepeater. /// - public IEnumerable? Items + public IEnumerable? ItemsSource { - get => _items; - set => SetAndRaise(ItemsProperty, ref _items, value); + get => _itemsSource; + set => SetAndRaise(ItemsSourceProperty, ref _itemsSource, value); } /// /// Gets or sets the template used to display each item. /// - [InheritDataTypeFromItems(nameof(Items))] + [InheritDataTypeFromItems(nameof(ItemsSource))] public IDataTemplate? ItemTemplate { get => GetValue(ItemTemplateProperty); @@ -415,7 +415,7 @@ namespace Avalonia.Controls /// protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { - if (change.Property == ItemsProperty) + if (change.Property == ItemsSourceProperty) { var (oldEnumerable, newEnumerable) = change.GetOldAndNewValue(); diff --git a/src/Avalonia.Controls/AutoCompleteBox/AutoCompleteBox.Properties.cs b/src/Avalonia.Controls/AutoCompleteBox/AutoCompleteBox.Properties.cs index b38151854b..47a0c531ba 100644 --- a/src/Avalonia.Controls/AutoCompleteBox/AutoCompleteBox.Properties.cs +++ b/src/Avalonia.Controls/AutoCompleteBox/AutoCompleteBox.Properties.cs @@ -143,12 +143,12 @@ namespace Avalonia.Controls nameof(TextSelector)); /// - /// Identifies the property. + /// Identifies the property. /// - /// The identifier for the property. - public static readonly StyledProperty ItemsProperty = + /// The identifier for the property. + public static readonly StyledProperty ItemsSourceProperty = AvaloniaProperty.Register( - nameof(Items)); + nameof(ItemsSource)); /// /// Identifies the property. @@ -311,10 +311,10 @@ namespace Avalonia.Controls /// /// Gets the text that is used to filter items in the - /// item collection. + /// item collection. /// /// The text that is used to filter items in the - /// item collection. + /// item collection. /// /// The SearchText value is typically the same as the /// Text property, but is set after the TextChanged event occurs @@ -339,7 +339,7 @@ namespace Avalonia.Controls /// /// Gets or sets how the text in the text box is used to filter items - /// specified by the + /// specified by the /// property for display in the drop-down. /// /// One of the @@ -366,11 +366,11 @@ namespace Avalonia.Controls /// /// Gets or sets the custom method that uses user-entered text to filter - /// the items specified by the + /// the items specified by the /// property for display in the drop-down. /// /// The custom method that uses the user-entered text to filter - /// the items specified by the + /// the items specified by the /// property. The default is null. /// /// The filter mode is automatically set to Custom if you set the @@ -384,11 +384,11 @@ namespace Avalonia.Controls /// /// Gets or sets the custom method that uses the user-entered text to - /// filter items specified by the + /// filter items specified by the /// property in a text-based way for display in the drop-down. /// /// The custom method that uses the user-entered text to filter - /// items specified by the + /// items specified by the /// property in a text-based way for display in the drop-down. /// /// The search mode is automatically set to Custom if you set the @@ -402,11 +402,11 @@ namespace Avalonia.Controls /// /// Gets or sets the custom method that combines the user-entered - /// text and one of the items specified by the . + /// text and one of the items specified by the . /// /// /// The custom method that combines the user-entered - /// text and one of the items specified by the . + /// text and one of the items specified by the . /// public AutoCompleteSelector? ItemSelector { @@ -417,11 +417,11 @@ namespace Avalonia.Controls /// /// Gets or sets the custom method that combines the user-entered /// text and one of the items specified by the - /// in a text-based way. + /// in a text-based way. /// /// /// The custom method that combines the user-entered - /// text and one of the items specified by the + /// text and one of the items specified by the /// in a text-based way. /// public AutoCompleteSelector? TextSelector @@ -442,10 +442,10 @@ namespace Avalonia.Controls /// /// The collection that is used to generate the items of the /// drop-down portion of the control. - public IEnumerable? Items + public IEnumerable? ItemsSource { - get => GetValue(ItemsProperty); - set => SetValue(ItemsProperty, value); + get => GetValue(ItemsSourceProperty); + set => SetValue(ItemsSourceProperty, value); } } } diff --git a/src/Avalonia.Controls/AutoCompleteBox/AutoCompleteBox.cs b/src/Avalonia.Controls/AutoCompleteBox/AutoCompleteBox.cs index 72a23144cf..e10cc1d100 100644 --- a/src/Avalonia.Controls/AutoCompleteBox/AutoCompleteBox.cs +++ b/src/Avalonia.Controls/AutoCompleteBox/AutoCompleteBox.cs @@ -419,9 +419,9 @@ namespace Avalonia.Controls /// ItemsSourceProperty property changed handler. /// /// Event arguments. - private void OnItemsPropertyChanged(AvaloniaPropertyChangedEventArgs e) + private void OnItemsSourcePropertyChanged(AvaloniaPropertyChangedEventArgs e) { - OnItemsChanged((IEnumerable?)e.NewValue); + OnItemsSourceChanged((IEnumerable?)e.NewValue); } private void OnItemTemplatePropertyChanged(AvaloniaPropertyChangedEventArgs e) @@ -461,7 +461,7 @@ namespace Avalonia.Controls SearchTextProperty.Changed.AddClassHandler((x,e) => x.OnSearchTextPropertyChanged(e)); FilterModeProperty.Changed.AddClassHandler((x,e) => x.OnFilterModePropertyChanged(e)); ItemFilterProperty.Changed.AddClassHandler((x,e) => x.OnItemFilterPropertyChanged(e)); - ItemsProperty.Changed.AddClassHandler((x,e) => x.OnItemsPropertyChanged(e)); + ItemsSourceProperty.Changed.AddClassHandler((x,e) => x.OnItemsSourcePropertyChanged(e)); ItemTemplateProperty.Changed.AddClassHandler((x,e) => x.OnItemTemplatePropertyChanged(e)); IsEnabledProperty.Changed.AddClassHandler((x,e) => x.OnControlIsEnabledChanged(e)); } @@ -559,7 +559,7 @@ namespace Avalonia.Controls _adapter.Commit -= OnAdapterSelectionComplete; _adapter.Cancel -= OnAdapterSelectionCanceled; _adapter.Cancel -= OnAdapterSelectionComplete; - _adapter.Items = null; + _adapter.ItemsSource = null; } _adapter = value; @@ -570,7 +570,7 @@ namespace Avalonia.Controls _adapter.Commit += OnAdapterSelectionComplete; _adapter.Cancel += OnAdapterSelectionCanceled; _adapter.Cancel += OnAdapterSelectionComplete; - _adapter.Items = _view; + _adapter.ItemsSource = _view; } } } @@ -1128,7 +1128,7 @@ namespace Avalonia.Controls { if (!cancellationToken.IsCancellationRequested) { - SetCurrentValue(ItemsProperty, resultList); + SetCurrentValue(ItemsSourceProperty, resultList); PopulateComplete(); } }); @@ -1475,7 +1475,7 @@ namespace Avalonia.Controls /// adapter's ItemsSource to the view if appropriate. /// /// The new enumerable reference. - private void OnItemsChanged(IEnumerable? newValue) + private void OnItemsSourceChanged(IEnumerable? newValue) { // Remove handler for oldValue.CollectionChanged (if present) _collectionChangeSubscription?.Dispose(); @@ -1492,9 +1492,9 @@ namespace Avalonia.Controls // Clear and set the view on the selection adapter ClearView(); - if (SelectionAdapter != null && SelectionAdapter.Items != _view) + if (SelectionAdapter != null && SelectionAdapter.ItemsSource != _view) { - SelectionAdapter.Items = _view; + SelectionAdapter.ItemsSource = _view; } if (IsDropDownOpen) { @@ -1545,9 +1545,9 @@ namespace Avalonia.Controls { // Significant changes to the underlying data. ClearView(); - if (Items != null) + if (ItemsSource != null) { - _items = new List(Items.Cast()); + _items = new List(ItemsSource.Cast()); } } @@ -1582,9 +1582,9 @@ namespace Avalonia.Controls PopulatedEventArgs populated = new PopulatedEventArgs(new ReadOnlyCollection(_view!)); OnPopulated(populated); - if (SelectionAdapter != null && SelectionAdapter.Items != _view) + if (SelectionAdapter != null && SelectionAdapter.ItemsSource != _view) { - SelectionAdapter.Items = _view; + SelectionAdapter.ItemsSource = _view; } bool isDropDownOpen = _userCalledPopulate && (_view!.Count > 0); diff --git a/src/Avalonia.Controls/CalendarDatePicker/CalendarDatePicker.cs b/src/Avalonia.Controls/CalendarDatePicker/CalendarDatePicker.cs index c091d07632..90153d3293 100644 --- a/src/Avalonia.Controls/CalendarDatePicker/CalendarDatePicker.cs +++ b/src/Avalonia.Controls/CalendarDatePicker/CalendarDatePicker.cs @@ -875,10 +875,11 @@ namespace Avalonia.Controls { if (_textBox != null) { + SetCurrentValue(TextProperty, String.Empty); + if (string.IsNullOrEmpty(Watermark) && !UseFloatingWatermark) { DateTimeFormatInfo dtfi = DateTimeHelper.GetCurrentDateFormat(); - SetCurrentValue(TextProperty, string.Empty); _defaultText = string.Empty; var watermarkFormat = "<{0}>"; string watermarkText; diff --git a/src/Avalonia.Controls/Flyouts/MenuFlyout.cs b/src/Avalonia.Controls/Flyouts/MenuFlyout.cs index 8e1bc214a7..a2ce93ee6d 100644 --- a/src/Avalonia.Controls/Flyouts/MenuFlyout.cs +++ b/src/Avalonia.Controls/Flyouts/MenuFlyout.cs @@ -1,6 +1,5 @@ using System.Collections; using System.ComponentModel; -using Avalonia.Collections; using Avalonia.Controls.Primitives; using Avalonia.Controls.Templates; using Avalonia.Metadata; @@ -12,17 +11,15 @@ namespace Avalonia.Controls { public MenuFlyout() { - _items = new AvaloniaList(); + Items = new ItemCollection(); } /// - /// Defines the property + /// Defines the property /// - public static readonly DirectProperty ItemsProperty = - AvaloniaProperty.RegisterDirect( - nameof(Items), - x => x.Items, - (x, v) => x.Items = v); + public static readonly StyledProperty ItemsSourceProperty = + AvaloniaProperty.Register( + nameof(ItemsSource)); /// /// Defines the property @@ -45,14 +42,16 @@ namespace Avalonia.Controls public Classes FlyoutPresenterClasses => _classes ??= new Classes(); + [Content] + public ItemCollection Items { get; } + /// /// Gets or sets the items of the MenuFlyout /// - [Content] - public IEnumerable? Items + public IEnumerable? ItemsSource { - get => _items; - set => SetAndRaise(ItemsProperty, ref _items, value); + get => GetValue(ItemsSourceProperty); + set => SetValue(ItemsSourceProperty, value); } /// @@ -83,14 +82,13 @@ namespace Avalonia.Controls } private Classes? _classes; - private IEnumerable? _items; private IDataTemplate? _itemTemplate; protected override Control CreatePresenter() { return new MenuFlyoutPresenter { - [!ItemsControl.ItemsSourceProperty] = this[!ItemsProperty], + ItemsSource = Items, [!ItemsControl.ItemTemplateProperty] = this[!ItemTemplateProperty], [!ItemsControl.ItemContainerThemeProperty] = this[!ItemContainerThemeProperty], }; @@ -113,5 +111,13 @@ namespace Avalonia.Controls base.OnOpening(args); } + + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + { + base.OnPropertyChanged(change); + + if (change.Property == ItemsSourceProperty) + Items.SetItemsSource(change.GetNewValue()); + } } } diff --git a/src/Avalonia.Controls/ItemsControl.cs b/src/Avalonia.Controls/ItemsControl.cs index 60b0f8b193..1c62de9bed 100644 --- a/src/Avalonia.Controls/ItemsControl.cs +++ b/src/Avalonia.Controls/ItemsControl.cs @@ -378,48 +378,48 @@ namespace Avalonia.Controls if (container is HeaderedContentControl hcc) { - hcc.Content = item; + SetIfUnset(hcc, HeaderedContentControl.ContentProperty, item); if (item is IHeadered headered) - hcc.Header = headered.Header; + SetIfUnset(hcc, HeaderedContentControl.HeaderProperty, headered.Header); else if (item is not Visual) - hcc.Header = item; + SetIfUnset(hcc, HeaderedContentControl.HeaderProperty, item); if (itemTemplate is not null) - hcc.HeaderTemplate = itemTemplate; + SetIfUnset(hcc, HeaderedContentControl.HeaderTemplateProperty, itemTemplate); } else if (container is ContentControl cc) { - cc.Content = item; + SetIfUnset(cc, ContentControl.ContentProperty, item); if (itemTemplate is not null) - cc.ContentTemplate = itemTemplate; + SetIfUnset(cc, ContentControl.ContentTemplateProperty, itemTemplate); } else if (container is ContentPresenter p) { - p.Content = item; + SetIfUnset(p, ContentPresenter.ContentProperty, item); if (itemTemplate is not null) - p.ContentTemplate = itemTemplate; + SetIfUnset(p, ContentPresenter.ContentTemplateProperty, itemTemplate); } else if (container is ItemsControl ic) { if (itemTemplate is not null) - ic.ItemTemplate = itemTemplate; - if (ItemContainerTheme is { } ict && !ict.IsSet(ItemContainerThemeProperty)) - ic.ItemContainerTheme = ict; + SetIfUnset(ic, ItemTemplateProperty, itemTemplate); + if (ItemContainerTheme is { } ict) + SetIfUnset(ic, ItemContainerThemeProperty, ict); } // These conditions are separate because HeaderedItemsControl and // HeaderedSelectingItemsControl also need to run the ItemsControl preparation. if (container is HeaderedItemsControl hic) { - hic.Header = item; - hic.HeaderTemplate = itemTemplate; + SetIfUnset(hic, HeaderedItemsControl.HeaderProperty, item); + SetIfUnset(hic, HeaderedItemsControl.HeaderTemplateProperty, itemTemplate); hic.PrepareItemContainer(this); } else if (container is HeaderedSelectingItemsControl hsic) { - hsic.Header = item; - hsic.HeaderTemplate = itemTemplate; + SetIfUnset(hsic, HeaderedSelectingItemsControl.HeaderProperty, item); + SetIfUnset(hsic, HeaderedSelectingItemsControl.HeaderTemplateProperty, itemTemplate); hsic.PrepareItemContainer(this); } } @@ -458,30 +458,35 @@ namespace Avalonia.Controls { if (container is HeaderedContentControl hcc) { - if (hcc.Content is Control) - hcc.Content = null; - if (hcc.Header is Control) - hcc.Header = null; + hcc.ClearValue(HeaderedContentControl.ContentProperty); + hcc.ClearValue(HeaderedContentControl.HeaderProperty); + hcc.ClearValue(HeaderedContentControl.HeaderTemplateProperty); } else if (container is ContentControl cc) { - if (cc.Content is Control) - cc.Content = null; + cc.ClearValue(ContentControl.ContentProperty); + cc.ClearValue(ContentControl.ContentTemplateProperty); } else if (container is ContentPresenter p) { - if (p.Content is Control) - p.Content = null; + p.ClearValue(ContentPresenter.ContentProperty); + p.ClearValue(ContentPresenter.ContentTemplateProperty); } - else if (container is HeaderedItemsControl hic) + else if (container is ItemsControl ic) + { + ic.ClearValue(ItemTemplateProperty); + ic.ClearValue(ItemContainerThemeProperty); + } + + if (container is HeaderedItemsControl hic) { - if (hic.Header is Control) - hic.Header = null; + hic.ClearValue(HeaderedItemsControl.HeaderProperty); + hic.ClearValue(HeaderedItemsControl.HeaderTemplateProperty); } else if (container is HeaderedSelectingItemsControl hsic) { - if (hsic.Header is Control) - hsic.Header = null; + hsic.ClearValue(HeaderedSelectingItemsControl.HeaderProperty); + hsic.ClearValue(HeaderedSelectingItemsControl.HeaderTemplateProperty); } // Feels like we should be clearing the HeaderedItemsControl.Items binding here, but looking at @@ -707,6 +712,12 @@ namespace Avalonia.Controls LogicalChildren.AddRange(toAdd); } + private void SetIfUnset(AvaloniaObject target, StyledProperty property, T value) + { + if (!target.IsSet(property)) + target.SetCurrentValue(property, value); + } + private void RemoveControlItemsFromLogicalChildren(IEnumerable? items) { if (items is null) diff --git a/src/Avalonia.Controls/ItemsSourceView.cs b/src/Avalonia.Controls/ItemsSourceView.cs index 614b70d0ba..977d712371 100644 --- a/src/Avalonia.Controls/ItemsSourceView.cs +++ b/src/Avalonia.Controls/ItemsSourceView.cs @@ -262,7 +262,7 @@ namespace Avalonia.Controls _source = source switch { - ItemsSourceView => throw new ArgumentException("Cannot wrap an existing ItemsSourceView.", nameof(source)), + ItemsSourceView isv => isv.Source, IList list => list, INotifyCollectionChanged => throw new ArgumentException( "Collection implements INotifyCollectionChanged but not IList.", diff --git a/src/Avalonia.Controls/RadioButton.cs b/src/Avalonia.Controls/RadioButton.cs index d4528fdb1c..f48ae72312 100644 --- a/src/Avalonia.Controls/RadioButton.cs +++ b/src/Avalonia.Controls/RadioButton.cs @@ -86,7 +86,7 @@ namespace Avalonia.Controls continue; } if (current != radioButton && current.IsChecked.GetValueOrDefault()) - current.IsChecked = false; + current.SetCurrentValue(IsCheckedProperty, false); i++; } if (group.Count == 0) @@ -193,7 +193,7 @@ namespace Avalonia.Controls foreach (var sibling in siblings) { if (sibling.IsChecked.GetValueOrDefault()) - sibling.IsChecked = false; + sibling.SetCurrentValue(IsCheckedProperty, false); } } } diff --git a/src/Avalonia.Controls/Templates/FuncControlTemplate.cs b/src/Avalonia.Controls/Templates/FuncControlTemplate.cs index 64a883e88c..895ce53907 100644 --- a/src/Avalonia.Controls/Templates/FuncControlTemplate.cs +++ b/src/Avalonia.Controls/Templates/FuncControlTemplate.cs @@ -18,10 +18,10 @@ namespace Avalonia.Controls.Templates { } - public new ControlTemplateResult Build(TemplatedControl param) + public new TemplateResult Build(TemplatedControl param) { var (control, scope) = BuildWithNameScope(param); - return new ControlTemplateResult(control, scope); + return new(control, scope); } } } diff --git a/src/Avalonia.Controls/Templates/IControlTemplate.cs b/src/Avalonia.Controls/Templates/IControlTemplate.cs index 38ad6561ab..c3f9c9e8aa 100644 --- a/src/Avalonia.Controls/Templates/IControlTemplate.cs +++ b/src/Avalonia.Controls/Templates/IControlTemplate.cs @@ -5,23 +5,7 @@ namespace Avalonia.Controls.Templates /// /// Interface representing a template used to build a . /// - public interface IControlTemplate : ITemplate + public interface IControlTemplate : ITemplate?> { } - - public class ControlTemplateResult : TemplateResult - { - public Control Control { get; } - - public ControlTemplateResult(Control control, INameScope nameScope) : base(control, nameScope) - { - Control = control; - } - - public new void Deconstruct(out Control control, out INameScope scope) - { - control = Control; - scope = NameScope; - } - } } diff --git a/src/Avalonia.Controls/Utils/ISelectionAdapter.cs b/src/Avalonia.Controls/Utils/ISelectionAdapter.cs index 3ede518ffa..55739500a1 100644 --- a/src/Avalonia.Controls/Utils/ISelectionAdapter.cs +++ b/src/Avalonia.Controls/Utils/ISelectionAdapter.cs @@ -36,7 +36,7 @@ namespace Avalonia.Controls.Utils /// /// The collection that is used to generate content for the /// selection adapter. - IEnumerable? Items { get; set; } + IEnumerable? ItemsSource { get; set; } /// /// Occurs when a selected item is not cancelled and is committed as the diff --git a/src/Avalonia.Controls/Utils/SelectingItemsControlSelectionAdapter.cs b/src/Avalonia.Controls/Utils/SelectingItemsControlSelectionAdapter.cs index 5f528e2c72..ca8827eb45 100644 --- a/src/Avalonia.Controls/Utils/SelectingItemsControlSelectionAdapter.cs +++ b/src/Avalonia.Controls/Utils/SelectingItemsControlSelectionAdapter.cs @@ -140,7 +140,7 @@ namespace Avalonia.Controls.Utils /// /// The collection used to generate content for the selection /// adapter. - public IEnumerable? Items + public IEnumerable? ItemsSource { get { diff --git a/src/Avalonia.Diagnostics/Diagnostics/Views/ControlDetailsView.xaml b/src/Avalonia.Diagnostics/Diagnostics/Views/ControlDetailsView.xaml index c2e63da31c..63b002d110 100644 --- a/src/Avalonia.Diagnostics/Diagnostics/Views/ControlDetailsView.xaml +++ b/src/Avalonia.Diagnostics/Diagnostics/Views/ControlDetailsView.xaml @@ -51,7 +51,7 @@ @@ -26,12 +26,6 @@ - - - - - - diff --git a/src/Avalonia.Themes.Simple/Controls/TextBox.xaml b/src/Avalonia.Themes.Simple/Controls/TextBox.xaml index 0c7095f2f5..20816c4c0b 100644 --- a/src/Avalonia.Themes.Simple/Controls/TextBox.xaml +++ b/src/Avalonia.Themes.Simple/Controls/TextBox.xaml @@ -13,15 +13,6 @@ IsEnabled="{Binding $parent[TextBox].CanPaste}" InputGesture="{x:Static TextBox.PasteGesture}" /> - - - - - - diff --git a/src/Markup/Avalonia.Markup.Xaml/Templates/ControlTemplate.cs b/src/Markup/Avalonia.Markup.Xaml/Templates/ControlTemplate.cs index 4bbdda31d8..b94eccf7c0 100644 --- a/src/Markup/Avalonia.Markup.Xaml/Templates/ControlTemplate.cs +++ b/src/Markup/Avalonia.Markup.Xaml/Templates/ControlTemplate.cs @@ -1,4 +1,5 @@ using System; +using Avalonia.Controls; using Avalonia.Controls.Primitives; using Avalonia.Controls.Templates; using Avalonia.Metadata; @@ -13,6 +14,6 @@ namespace Avalonia.Markup.Xaml.Templates public Type? TargetType { get; set; } - public ControlTemplateResult? Build(TemplatedControl control) => TemplateContent.Load(Content); + public TemplateResult? Build(TemplatedControl control) => TemplateContent.Load(Content); } } diff --git a/src/Markup/Avalonia.Markup.Xaml/Templates/DataTemplate.cs b/src/Markup/Avalonia.Markup.Xaml/Templates/DataTemplate.cs index 89b0468c6e..b45898d8bd 100644 --- a/src/Markup/Avalonia.Markup.Xaml/Templates/DataTemplate.cs +++ b/src/Markup/Avalonia.Markup.Xaml/Templates/DataTemplate.cs @@ -30,7 +30,7 @@ namespace Avalonia.Markup.Xaml.Templates public Control? Build(object? data, Control? existing) { - return existing ?? TemplateContent.Load(Content)?.Control; + return existing ?? TemplateContent.Load(Content)?.Result; } } } diff --git a/src/Markup/Avalonia.Markup.Xaml/Templates/ItemsPanelTemplate.cs b/src/Markup/Avalonia.Markup.Xaml/Templates/ItemsPanelTemplate.cs index c228a58990..f31a693e72 100644 --- a/src/Markup/Avalonia.Markup.Xaml/Templates/ItemsPanelTemplate.cs +++ b/src/Markup/Avalonia.Markup.Xaml/Templates/ItemsPanelTemplate.cs @@ -10,7 +10,7 @@ namespace Avalonia.Markup.Xaml.Templates [TemplateContent] public object? Content { get; set; } - public Panel? Build() => (Panel?)TemplateContent.Load(Content)?.Control; + public Panel? Build() => (Panel?)TemplateContent.Load(Content)?.Result; object? ITemplate.Build() => Build(); } diff --git a/src/Markup/Avalonia.Markup.Xaml/Templates/Template.cs b/src/Markup/Avalonia.Markup.Xaml/Templates/Template.cs index 62febebc8c..5999a8021e 100644 --- a/src/Markup/Avalonia.Markup.Xaml/Templates/Template.cs +++ b/src/Markup/Avalonia.Markup.Xaml/Templates/Template.cs @@ -10,7 +10,7 @@ namespace Avalonia.Markup.Xaml.Templates [TemplateContent] public object? Content { get; set; } - public Control? Build() => TemplateContent.Load(Content)?.Control; + public Control? Build() => TemplateContent.Load(Content)?.Result; object? ITemplate.Build() => Build(); } diff --git a/src/Markup/Avalonia.Markup.Xaml/Templates/TemplateContent.cs b/src/Markup/Avalonia.Markup.Xaml/Templates/TemplateContent.cs index 08e897c514..504478f9b3 100644 --- a/src/Markup/Avalonia.Markup.Xaml/Templates/TemplateContent.cs +++ b/src/Markup/Avalonia.Markup.Xaml/Templates/TemplateContent.cs @@ -1,15 +1,16 @@ using System; +using Avalonia.Controls; using Avalonia.Controls.Templates; namespace Avalonia.Markup.Xaml.Templates { public static class TemplateContent { - public static ControlTemplateResult? Load(object? templateContent) + public static TemplateResult? Load(object? templateContent) { if (templateContent is Func direct) { - return (ControlTemplateResult?)direct(null); + return (TemplateResult?)direct(null); } if (templateContent is null) diff --git a/src/Markup/Avalonia.Markup.Xaml/Templates/TreeDataTemplate.cs b/src/Markup/Avalonia.Markup.Xaml/Templates/TreeDataTemplate.cs index a5b308523f..98c3b61c9f 100644 --- a/src/Markup/Avalonia.Markup.Xaml/Templates/TreeDataTemplate.cs +++ b/src/Markup/Avalonia.Markup.Xaml/Templates/TreeDataTemplate.cs @@ -54,7 +54,7 @@ namespace Avalonia.Markup.Xaml.Templates public Control? Build(object? data) { - var visualTreeForItem = TemplateContent.Load(Content)?.Control; + var visualTreeForItem = TemplateContent.Load(Content)?.Result; if (visualTreeForItem != null) { visualTreeForItem.DataContext = data; diff --git a/src/Markup/Avalonia.Markup.Xaml/XamlIl/Runtime/XamlIlRuntimeHelpers.cs b/src/Markup/Avalonia.Markup.Xaml/XamlIl/Runtime/XamlIlRuntimeHelpers.cs index ba96ac15b3..0cc7cc5468 100644 --- a/src/Markup/Avalonia.Markup.Xaml/XamlIl/Runtime/XamlIlRuntimeHelpers.cs +++ b/src/Markup/Avalonia.Markup.Xaml/XamlIl/Runtime/XamlIlRuntimeHelpers.cs @@ -35,7 +35,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.Runtime scope.Complete(); if(typeof(T) == typeof(Control)) - return new ControlTemplateResult((Control)obj, scope); + return new TemplateResult((Control)obj, scope); return new TemplateResult((T)obj, scope); }; diff --git a/tests/Avalonia.Controls.ItemsRepeater.UnitTests/ItemsRepeaterTests.cs b/tests/Avalonia.Controls.ItemsRepeater.UnitTests/ItemsRepeaterTests.cs index 321676abc0..3c4777688d 100644 --- a/tests/Avalonia.Controls.ItemsRepeater.UnitTests/ItemsRepeaterTests.cs +++ b/tests/Avalonia.Controls.ItemsRepeater.UnitTests/ItemsRepeaterTests.cs @@ -9,16 +9,16 @@ namespace Avalonia.Controls.UnitTests public void Can_Reassign_Items() { var target = new ItemsRepeater(); - target.Items = new ObservableCollection(); - target.Items = new ObservableCollection(); + target.ItemsSource = new ObservableCollection(); + target.ItemsSource = new ObservableCollection(); } [Fact] public void Can_Reassign_Items_To_Null() { var target = new ItemsRepeater(); - target.Items = new ObservableCollection(); - target.Items = null; + target.ItemsSource = new ObservableCollection(); + target.ItemsSource = null; } } } diff --git a/tests/Avalonia.Controls.UnitTests/AutoCompleteBoxTests.cs b/tests/Avalonia.Controls.UnitTests/AutoCompleteBoxTests.cs index 4582659763..acae583b5c 100644 --- a/tests/Avalonia.Controls.UnitTests/AutoCompleteBoxTests.cs +++ b/tests/Avalonia.Controls.UnitTests/AutoCompleteBoxTests.cs @@ -89,7 +89,7 @@ namespace Avalonia.Controls.UnitTests bool closeEvent = false; control.DropDownOpened += (s, e) => openEvent = true; control.DropDownClosed += (s, e) => closeEvent = true; - control.Items = CreateSimpleStringArray(); + control.ItemsSource = CreateSimpleStringArray(); textbox.Text = "a"; Dispatcher.UIThread.RunJobs(); @@ -258,7 +258,7 @@ namespace Avalonia.Controls.UnitTests control.FilterMode = AutoCompleteFilterMode.None; control.Populating += (s, e) => { - control.Items = new string[] { custom }; + control.ItemsSource = new string[] { custom }; Assert.Equal(search, e.Parameter); }; control.Populated += (s, e) => @@ -380,7 +380,7 @@ namespace Avalonia.Controls.UnitTests { RunTest((control, textbox) => { - object selectedItem = control.Items.Cast().First(); + object selectedItem = control.ItemsSource.Cast().First(); string input = "42"; control.TextSelector = (text, item) => text + item; @@ -397,7 +397,7 @@ namespace Avalonia.Controls.UnitTests { RunTest((control, textbox) => { - object selectedItem = control.Items.Cast().First(); + object selectedItem = control.ItemsSource.Cast().First(); string input = "42"; control.ItemSelector = (text, item) => text + item; @@ -1053,7 +1053,7 @@ namespace Avalonia.Controls.UnitTests using (UnitTestApplication.Start(Services)) { AutoCompleteBox control = CreateControl(); - control.Items = CreateSimpleStringArray(); + control.ItemsSource = CreateSimpleStringArray(); TextBox textBox = GetTextBox(control); var window = new Window {Content = control}; window.ApplyStyling(); diff --git a/tests/Avalonia.Controls.UnitTests/ListBoxTests.cs b/tests/Avalonia.Controls.UnitTests/ListBoxTests.cs index 7a227a48ab..84eed5ec82 100644 --- a/tests/Avalonia.Controls.UnitTests/ListBoxTests.cs +++ b/tests/Avalonia.Controls.UnitTests/ListBoxTests.cs @@ -554,6 +554,36 @@ namespace Avalonia.Controls.UnitTests Assert.Equal(new[] { "Bar" }, target.Selection.SelectedItems); } + [Fact] + public void Content_Can_Be_Bound_In_ItemContainerTheme() + { + using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface)) + { + var items = new[] { new ItemViewModel("Foo"), new ItemViewModel("Bar") }; + var theme = new ControlTheme(typeof(ListBoxItem)) + { + Setters = + { + new Setter(ListBoxItem.ContentProperty, new Binding("Caption")), + } + }; + + var target = new ListBox + { + Template = ListBoxTemplate(), + ItemsSource = items, + ItemContainerTheme = theme, + }; + + Prepare(target); + + var containers = target.GetRealizedContainers().Cast().ToList(); + Assert.Equal(2, containers.Count); + Assert.Equal("Foo", containers[0].Content); + Assert.Equal("Bar", containers[1].Content); + } + } + private static FuncControlTemplate ListBoxTemplate() { return new FuncControlTemplate((parent, scope) => @@ -918,6 +948,8 @@ namespace Avalonia.Controls.UnitTests Assert.Equal(1, raised); } + private record ItemViewModel(string Caption); + private class ResettingCollection : List, INotifyCollectionChanged { public ResettingCollection(int itemCount) diff --git a/tests/Avalonia.Controls.UnitTests/MaskedTextBoxTests.cs b/tests/Avalonia.Controls.UnitTests/MaskedTextBoxTests.cs index a51abdb9af..9fd56dec4a 100644 --- a/tests/Avalonia.Controls.UnitTests/MaskedTextBoxTests.cs +++ b/tests/Avalonia.Controls.UnitTests/MaskedTextBoxTests.cs @@ -72,7 +72,7 @@ namespace Avalonia.Controls.UnitTests Text = "1234", ContextFlyout = new MenuFlyout { - Items = new List + Items = { new MenuItem { Header = "Item 1" }, new MenuItem {Header = "Item 2" }, diff --git a/tests/Avalonia.Controls.UnitTests/MenuItemTests.cs b/tests/Avalonia.Controls.UnitTests/MenuItemTests.cs index bbe46b2b21..08aedceac3 100644 --- a/tests/Avalonia.Controls.UnitTests/MenuItemTests.cs +++ b/tests/Avalonia.Controls.UnitTests/MenuItemTests.cs @@ -1,16 +1,16 @@ using System; +using System.Collections; using System.Collections.Generic; -using System.Text; +using System.Linq; using System.Windows.Input; -using Avalonia.Collections; using Avalonia.Controls.Presenters; -using Avalonia.Controls.Primitives; using Avalonia.Controls.Templates; +using Avalonia.Controls.Utils; using Avalonia.Data; using Avalonia.Input; using Avalonia.Platform; +using Avalonia.Styling; using Avalonia.UnitTests; -using Avalonia.VisualTree; using Moq; using Xunit; @@ -36,7 +36,6 @@ namespace Avalonia.Controls.UnitTests Assert.False(target.Focusable); } - [Fact] public void MenuItem_Is_Disabled_When_Command_Is_Enabled_But_IsEnabled_Is_False() { @@ -232,7 +231,7 @@ namespace Avalonia.Controls.UnitTests return true; }); var target = new MenuItem(); - var flyout = new MenuFlyout { Items = new AvaloniaList { target } }; + var flyout = new MenuFlyout { Items = { target } }; var button = new Button { Flyout = flyout }; var window = new Window { Content = button }; window.ApplyStyling(); @@ -393,6 +392,87 @@ namespace Avalonia.Controls.UnitTests } } + [Fact] + public void Header_And_ItemsSource_Can_Be_Bound_In_Style() + { + using var app = Application(); + var items = new[] + { + new MenuViewModel("Foo") + { + Children = new[] + { + new MenuViewModel("FooChild"), + }, + }, + new MenuViewModel("Bar"), + }; + + var target = new Menu + { + ItemsSource = items, + Styles = + { + new Style(x => x.OfType()) + { + Setters = + { + new Setter(MenuItem.HeaderProperty, new Binding("Header")), + new Setter(MenuItem.ItemsSourceProperty, new Binding("Children")), + } + } + } + }; + + var root = new TestRoot(true, target); + root.LayoutManager.ExecuteInitialLayoutPass(); + + var children = target.GetRealizedContainers().Cast().ToList(); + Assert.Equal(2, children.Count); + Assert.Equal("Foo", children[0].Header); + Assert.Equal("Bar", children[1].Header); + Assert.Same(items[0].Children, children[0].ItemsSource); + } + + [Fact] + public void Header_And_ItemsSource_Can_Be_Bound_In_ItemContainerTheme() + { + using var app = Application(); + var items = new[] + { + new MenuViewModel("Foo") + { + Children = new[] + { + new MenuViewModel("FooChild"), + }, + }, + new MenuViewModel("Bar"), + }; + + var target = new Menu + { + ItemsSource = items, + ItemContainerTheme = new ControlTheme(typeof(MenuItem)) + { + Setters = + { + new Setter(MenuItem.HeaderProperty, new Binding("Header")), + new Setter(MenuItem.ItemsSourceProperty, new Binding("Children")), + } + } + }; + + var root = new TestRoot(true, target); + root.LayoutManager.ExecuteInitialLayoutPass(); + + var children = target.GetRealizedContainers().Cast().ToList(); + Assert.Equal(2, children.Count); + Assert.Equal("Foo", children[0].Header); + Assert.Equal("Bar", children[1].Header); + Assert.Same(items[0].Children, children[0].ItemsSource); + } + private IDisposable Application() { var screen = new PixelRect(new PixelPoint(), new PixelSize(100, 100)); @@ -447,6 +527,9 @@ namespace Avalonia.Controls.UnitTests public void RaiseCanExecuteChanged() => _canExecuteChanged?.Invoke(this, EventArgs.Empty); } - private record MenuViewModel(string Header); + private record MenuViewModel(string Header) + { + public IList Children { get; set;} + } } } diff --git a/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs b/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs index 0f0fd8f6c4..d71abe5a67 100644 --- a/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs +++ b/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs @@ -93,7 +93,7 @@ namespace Avalonia.Controls.UnitTests Text = "1234", ContextFlyout = new MenuFlyout { - Items = new List + Items = { new MenuItem { Header = "Item 1" }, new MenuItem {Header = "Item 2" }, diff --git a/tests/Avalonia.IntegrationTests.Appium/NativeMenuTests.cs b/tests/Avalonia.IntegrationTests.Appium/NativeMenuTests.cs index 20594a9774..eb7740aa43 100644 --- a/tests/Avalonia.IntegrationTests.Appium/NativeMenuTests.cs +++ b/tests/Avalonia.IntegrationTests.Appium/NativeMenuTests.cs @@ -18,7 +18,7 @@ namespace Avalonia.IntegrationTests.Appium } [PlatformFact(TestPlatforms.MacOS)] - public void View_Menu_Select_Button_Tab() + public void MacOS_View_Menu_Select_Button_Tab() { var tabs = _session.FindElementByAccessibilityId("MainTabs"); var buttonTab = tabs.FindElementByName("Button"); @@ -33,5 +33,21 @@ namespace Avalonia.IntegrationTests.Appium Assert.True(buttonTab.Selected); } + + [PlatformFact(TestPlatforms.Windows)] + public void Win32_View_Menu_Select_Button_Tab() + { + var tabs = _session.FindElementByAccessibilityId("MainTabs"); + var buttonTab = tabs.FindElementByName("Button"); + var viewMenu = _session.FindElementByXPath("//MenuItem[@Name='View']"); + + Assert.False(buttonTab.Selected); + + viewMenu.Click(); + var buttonMenu = viewMenu.FindElementByName("Button"); + buttonMenu.Click(); + + Assert.True(buttonTab.Selected); + } } } diff --git a/tests/Avalonia.LeakTests/ControlTests.cs b/tests/Avalonia.LeakTests/ControlTests.cs index 1320d34f39..55825561af 100644 --- a/tests/Avalonia.LeakTests/ControlTests.cs +++ b/tests/Avalonia.LeakTests/ControlTests.cs @@ -51,7 +51,7 @@ namespace Avalonia.LeakTests { Content = new DataGrid { - Items = _observableCollection + ItemsSource = _observableCollection } }; diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/CompiledBindingExtensionTests.cs b/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/CompiledBindingExtensionTests.cs index 57d6a8902a..9f0b84733d 100644 --- a/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/CompiledBindingExtensionTests.cs +++ b/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/CompiledBindingExtensionTests.cs @@ -1978,7 +1978,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions public bool Match(object data) => FancyDataType?.IsInstanceOfType(data) ?? true; - public Control Build(object data) => TemplateContent.Load(Content)?.Control; + public Control Build(object data) => TemplateContent.Load(Content)?.Result; } public class CustomDataTemplateInherit : CustomDataTemplate { } diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/BasicTests.cs b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/BasicTests.cs index 5e30198d00..421ed2c979 100644 --- a/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/BasicTests.cs +++ b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/BasicTests.cs @@ -605,7 +605,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.Xaml var control = new ContentControl(); - var result = (ContentPresenter)template.Build(control).Control; + var result = (ContentPresenter)template.Build(control).Result; Assert.NotNull(result); } diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/ControlTemplateTests.cs b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/ControlTemplateTests.cs index 0a45814efe..4404564733 100644 --- a/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/ControlTemplateTests.cs +++ b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/ControlTemplateTests.cs @@ -258,7 +258,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.Xaml "; var template = AvaloniaRuntimeXamlLoader.Parse(xaml); - var parent = (ContentControl)template.Build(new ContentControl()).Control; + var parent = (ContentControl)template.Build(new ContentControl()).Result; Assert.Equal("parent", parent.Name); @@ -283,7 +283,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.Xaml Assert.Equal(typeof(ContentControl), template.TargetType); - Assert.IsType(typeof(ContentPresenter), template.Build(new ContentControl()).Control); + Assert.IsType(typeof(ContentPresenter), template.Build(new ContentControl()).Result); } [Fact] @@ -299,7 +299,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.Xaml "; var template = AvaloniaRuntimeXamlLoader.Parse(xaml); - var panel = (Panel)template.Build(new ContentControl()).Control; + var panel = (Panel)template.Build(new ContentControl()).Result; Assert.Equal(2, panel.Children.Count); diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/StyleTests.cs b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/StyleTests.cs index 20a4543b72..2c20b7a0b7 100644 --- a/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/StyleTests.cs +++ b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/StyleTests.cs @@ -424,7 +424,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.Xaml }; var list = window.FindControl("list"); - list.Items = collection; + list.ItemsSource = collection; window.Show();