Add support for selection wrapping for ListBox, ItemsControl, ComboBox.
Co-authored-by: Steven Kirk <grokys@users.noreply.github.com>
Co-authored-by: Takoooooo <tako0qq@gmail.com>
Co-authored-by: Steven Kirk <grokys@gmail.com>
`SelectionModel` needs to subscribe to `CollectionChanged` on the items before `ItemsControl` in order for the selection to be correct when we come to setting the selected state.
Because `SelectionModel.Source` isn't subscribed during initialization in `ItemsChanged`, we also need to make sure we don't subscribe `ItemsControl` to the collection changes during initialization. Instead subscribe in `OnInitialized` (this requires a few tests to be rooted in order to be called).
Fixes#4293
Exposing the `ContentPresenter.Child` in `ItemsControl.LogicalChildren` was causing problems when detaching and reattaching an `ItemsControl` to the logical tree. Instead, expose the `ContentPresenter` itself in effect meaning that `ItemsControl` has a "container" type just like the controls derived from it.
Fixes#3487
Having a separate subscription to `Items.CollectionChanged` in both `ItemsControl` and `ItemsPresenter` meant that the `ItemsPresenter` sometimes doesn't update itself in time for a selection change, resulting in #3148. Make `ItemsControl` trigger `ItemsPresenter.ItemsChanged` rather than both controls listening to the event separately.
Removed the code that was causing the TreeView problems described in #2944. This code was never actually called except in `TreeView` because a plain `ItemsControl` can't be used with virtualization (it uses untyped `ItemContainerGenerator` so items can't be recycled) and every other derived class derives from SelectingItemsControl which overrides this method and doesn't call the base implementation. In addition there were no unit tests covering this code.
Fixes#2944
During initial layout, `TemplatedParent` is read tens of thousands of times. This being a styled property that used `inherits: true` meant that it was showing up in profiling as taking up a significant amount of time.
Make `TemplatedParent` a direct property so that reading it is a simple property access. This doesn't actually complicate the code much at all as once set the property value doesn't change, so `inherited: true` semantics are not that important.