diff --git a/src/Avalonia.Controls/Generators/TabItemContainerGenerator.cs b/src/Avalonia.Controls/Generators/TabItemContainerGenerator.cs index d99648a158..c216037aba 100644 --- a/src/Avalonia.Controls/Generators/TabItemContainerGenerator.cs +++ b/src/Avalonia.Controls/Generators/TabItemContainerGenerator.cs @@ -19,8 +19,6 @@ namespace Avalonia.Controls.Generators { var tabItem = (TabItem)base.CreateContainer(item); - tabItem.ParentTabControl = Owner; - tabItem[~TabControl.TabStripPlacementProperty] = Owner[~TabControl.TabStripPlacementProperty]; if (tabItem.HeaderTemplate == null) diff --git a/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs b/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs index b6ae567123..329b086a7c 100644 --- a/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs +++ b/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs @@ -367,17 +367,17 @@ namespace Avalonia.Controls.Primitives { if ((container.ContainerControl as ISelectable)?.IsSelected == true) { - if (SelectedIndex == -1) - { - SelectedIndex = container.Index; - } - else + if (SelectionMode.HasFlag(SelectionMode.Multiple)) { if (_selection.Add(container.Index)) { resetSelectedItems = true; } } + else + { + SelectedIndex = container.Index; + } MarkContainerSelected(container.ContainerControl, true); } diff --git a/src/Avalonia.Controls/TabControl.cs b/src/Avalonia.Controls/TabControl.cs index 61ac0822b0..8b1cd48379 100644 --- a/src/Avalonia.Controls/TabControl.cs +++ b/src/Avalonia.Controls/TabControl.cs @@ -4,7 +4,6 @@ using System.Linq; using Avalonia.Collections; using Avalonia.Controls.Generators; -using Avalonia.Controls.Mixins; using Avalonia.Controls.Presenters; using Avalonia.Controls.Primitives; using Avalonia.Controls.Templates; @@ -70,6 +69,7 @@ namespace Avalonia.Controls SelectionModeProperty.OverrideDefaultValue(SelectionMode.AlwaysSelected); ItemsPanelProperty.OverrideDefaultValue(DefaultPanel); AffectsMeasure(TabStripPlacementProperty); + SelectedIndexProperty.Changed.AddClassHandler((x, e) => x.UpdateSelectedContent(e)); } /// @@ -145,6 +145,61 @@ namespace Avalonia.Controls return RegisterContentPresenter(presenter); } + protected override void OnContainersMaterialized(ItemContainerEventArgs e) + { + base.OnContainersMaterialized(e); + + if (SelectedContent != null || SelectedIndex == -1) + { + return; + } + + var container = (TabItem)ItemContainerGenerator.ContainerFromIndex(SelectedIndex); + + if (container == null) + { + return; + } + + UpdateSelectedContent(container); + } + + private void UpdateSelectedContent(AvaloniaPropertyChangedEventArgs e) + { + var index = (int)e.NewValue; + + if (index == -1) + { + SelectedContentTemplate = null; + + SelectedContent = null; + + return; + } + + var container = (TabItem)ItemContainerGenerator.ContainerFromIndex(index); + + if (container == null) + { + return; + } + + UpdateSelectedContent(container); + } + + private void UpdateSelectedContent(IContentControl item) + { + if (SelectedContentTemplate != item.ContentTemplate) + { + SelectedContentTemplate = item.ContentTemplate; + } + + if (SelectedContent != item.Content) + { + SelectedContent = item.Content; + } + } + /// /// Called when an is registered with the control. /// diff --git a/src/Avalonia.Controls/TabItem.cs b/src/Avalonia.Controls/TabItem.cs index fca1e022aa..e27977bf3d 100644 --- a/src/Avalonia.Controls/TabItem.cs +++ b/src/Avalonia.Controls/TabItem.cs @@ -30,7 +30,6 @@ namespace Avalonia.Controls { SelectableMixin.Attach(IsSelectedProperty); FocusableProperty.OverrideDefaultValue(typeof(TabItem), true); - IsSelectedProperty.Changed.AddClassHandler((x, e) => x.UpdateSelectedContent(e)); DataContextProperty.Changed.AddClassHandler((x, e) => x.UpdateHeader(e)); } @@ -54,8 +53,6 @@ namespace Avalonia.Controls set { SetValue(IsSelectedProperty, value); } } - internal TabControl ParentTabControl { get; set; } - private void UpdateHeader(AvaloniaPropertyChangedEventArgs obj) { if (Header == null) @@ -83,23 +80,5 @@ namespace Avalonia.Controls } } } - - private void UpdateSelectedContent(AvaloniaPropertyChangedEventArgs e) - { - if (!IsSelected) - { - return; - } - - if (ParentTabControl.SelectedContentTemplate != ContentTemplate) - { - ParentTabControl.SelectedContentTemplate = ContentTemplate; - } - - if (ParentTabControl.SelectedContent != Content) - { - ParentTabControl.SelectedContent = Content; - } - } } } diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index 2ae200a179..9d35342fb9 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -621,7 +621,7 @@ namespace Avalonia.Win32 timestamp, _owner, RawPointerEventType.LeaveWindow, - new Point(), WindowsKeyboardDevice.Instance.Modifiers); + new Point(-1,-1), WindowsKeyboardDevice.Instance.Modifiers); break; case UnmanagedMethods.WindowsMessage.WM_NCLBUTTONDOWN: @@ -636,7 +636,7 @@ namespace Avalonia.Win32 : msg == (int)UnmanagedMethods.WindowsMessage.WM_NCRBUTTONDOWN ? RawPointerEventType.RightButtonDown : RawPointerEventType.MiddleButtonDown, - new Point(0, 0), GetMouseModifiers(wParam)); + PointToClient(PointFromLParam(lParam)), GetMouseModifiers(wParam)); break; case WindowsMessage.WM_TOUCH: var touchInputCount = wParam.ToInt32(); diff --git a/tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests.cs b/tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests.cs index 6df89ba444..d819581000 100644 --- a/tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests.cs +++ b/tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests.cs @@ -1185,6 +1185,33 @@ namespace Avalonia.Controls.UnitTests.Primitives target.MoveSelection(NavigationDirection.Next, true); } + [Fact] + public void Pre_Selecting_Item_Should_Set_Selection_After_It_Was_Added_When_AlwaysSelected() + { + var target = new TestSelector(SelectionMode.AlwaysSelected) + { + Template = Template() + }; + + var second = new Item { IsSelected = true }; + + var items = new AvaloniaList + { + new Item(), + second + }; + + target.Items = items; + + target.ApplyTemplate(); + + target.Presenter.ApplyTemplate(); + + Assert.Equal(second, target.SelectedItem); + + Assert.Equal(1, target.SelectedIndex); + } + private FuncControlTemplate Template() { return new FuncControlTemplate((control, scope) => @@ -1233,6 +1260,16 @@ namespace Avalonia.Controls.UnitTests.Primitives private class TestSelector : SelectingItemsControl { + public TestSelector() + { + + } + + public TestSelector(SelectionMode selectionMode) + { + SelectionMode = selectionMode; + } + public new bool MoveSelection(NavigationDirection direction, bool wrap) { return base.MoveSelection(direction, wrap); diff --git a/tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests_Multiple.cs b/tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests_Multiple.cs index be0f4272a5..952a00a14e 100644 --- a/tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests_Multiple.cs +++ b/tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests_Multiple.cs @@ -1080,6 +1080,7 @@ namespace Avalonia.Controls.UnitTests.Primitives var target = new TestSelector { Items = items, + SelectionMode = SelectionMode.Multiple, Template = Template(), }; diff --git a/tests/Avalonia.Controls.UnitTests/TabControlTests.cs b/tests/Avalonia.Controls.UnitTests/TabControlTests.cs index b65a4d67d4..a9e86d71ee 100644 --- a/tests/Avalonia.Controls.UnitTests/TabControlTests.cs +++ b/tests/Avalonia.Controls.UnitTests/TabControlTests.cs @@ -45,6 +45,29 @@ namespace Avalonia.Controls.UnitTests Assert.Equal(selected, target.SelectedItem); } + [Fact] + public void Pre_Selecting_TabItem_Should_Set_SelectedContent_After_It_Was_Added() + { + var target = new TabControl + { + Template = TabControlTemplate(), + }; + + const string secondContent = "Second"; + + var items = new AvaloniaList + { + new TabItem { Header = "First"}, + new TabItem { Header = "Second", Content = secondContent, IsSelected = true } + }; + + target.Items = items; + + ApplyTemplate(target); + + Assert.Equal(secondContent, target.SelectedContent); + } + [Fact] public void Logical_Children_Should_Be_TabItems() {