From a794c2a2c07d2411f07667878c9f151ded0fa060 Mon Sep 17 00:00:00 2001 From: NaBian <836904362@qq.com> Date: Wed, 13 May 2020 23:52:45 +0800 Subject: [PATCH] now you can use ItemsSource on Carousel --- .../UserControl/Controls/CarouselDemoCtl.xaml | 2 +- .../Controls/{Other => Carousel}/Carousel.cs | 177 ++++++++++++++++-- .../Controls/Carousel/CarouselItem.cs | 9 + .../Controls/Cover/CoverView/CoverView.cs | 12 +- .../HandyControl_Shared.projitems | 3 +- .../Themes/Styles/Carousel.xaml | 90 ++++++++- 6 files changed, 259 insertions(+), 34 deletions(-) rename src/Shared/HandyControl_Shared/Controls/{Other => Carousel}/Carousel.cs (65%) create mode 100644 src/Shared/HandyControl_Shared/Controls/Carousel/CarouselItem.cs diff --git a/src/Shared/HandyControlDemo_Shared/UserControl/Controls/CarouselDemoCtl.xaml b/src/Shared/HandyControlDemo_Shared/UserControl/Controls/CarouselDemoCtl.xaml index 89bbeefc..889109ad 100644 --- a/src/Shared/HandyControlDemo_Shared/UserControl/Controls/CarouselDemoCtl.xaml +++ b/src/Shared/HandyControlDemo_Shared/UserControl/Controls/CarouselDemoCtl.xaml @@ -9,7 +9,7 @@ - + diff --git a/src/Shared/HandyControl_Shared/Controls/Other/Carousel.cs b/src/Shared/HandyControl_Shared/Controls/Carousel/Carousel.cs similarity index 65% rename from src/Shared/HandyControl_Shared/Controls/Other/Carousel.cs rename to src/Shared/HandyControl_Shared/Controls/Carousel/Carousel.cs index 47ac493a..6ff7f180 100644 --- a/src/Shared/HandyControl_Shared/Controls/Other/Carousel.cs +++ b/src/Shared/HandyControl_Shared/Controls/Carousel/Carousel.cs @@ -1,4 +1,5 @@ using System; +using System.Collections; using System.Collections.Generic; using System.Collections.Specialized; using System.ComponentModel; @@ -21,13 +22,11 @@ namespace HandyControl.Controls [DefaultProperty("Items")] [ContentProperty("Items")] [TemplatePart(Name = ElementPanelPage, Type = typeof(Panel))] - [TemplatePart(Name = ElementItemsControl, Type = typeof(ItemsPresenter))] - public class Carousel : ListBox, IDisposable + public class Carousel : SimpleItemsControl, IDisposable { #region Constants private const string ElementPanelPage = "PART_PanelPage"; - private const string ElementItemsControl = "PART_ItemsControl"; #endregion Constants @@ -39,8 +38,6 @@ namespace HandyControl.Controls private bool _appliedTemplate; - private ItemsPresenter _itemsControl; - private int _pageIndex = -1; private RadioButton _selectedButton; @@ -49,6 +46,12 @@ namespace HandyControl.Controls private readonly List _widthList = new List(); + private readonly Dictionary _entryDic = new Dictionary(); + + private bool _isRefresh; + + private IEnumerable _itemsSourceInternal; + #endregion Data public override void OnApplyTemplate() @@ -59,7 +62,6 @@ namespace HandyControl.Controls base.OnApplyTemplate(); - _itemsControl = GetTemplateChild(ElementItemsControl) as ItemsPresenter; _panelPage = GetTemplateChild(ElementPanelPage) as Panel; if (!CheckNull()) return; @@ -75,7 +77,7 @@ namespace HandyControl.Controls UpdatePageButtons(_pageIndex); } - private bool CheckNull() => !(_itemsControl == null || _panelPage == null); + private bool CheckNull() => _panelPage != null; public static readonly DependencyProperty AutoRunProperty = DependencyProperty.Register( "AutoRun", typeof(bool), typeof(Carousel), new PropertyMetadata(ValueBoxes.FalseBox, (o, args) => @@ -153,13 +155,6 @@ namespace HandyControl.Controls } } - protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e) - { - base.OnItemsChanged(e); - - UpdatePageButtons(); - } - /// /// 是否自动跳转 /// @@ -239,14 +234,14 @@ namespace HandyControl.Controls _widthList.Clear(); _widthList.Add(0); var width = .0; - foreach (FrameworkElement item in Items) + foreach (FrameworkElement item in ItemsHost.Children) { item.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity)); width += item.DesiredSize.Width; _widthList.Add(width); } - _itemsControl.Width = _widthList.Last() + ExtendWidth; + ItemsHost.Width = _widthList.Last() + ExtendWidth; _panelPage.Children.Clear(); for (var i = 0; i < count; i++) { @@ -278,14 +273,14 @@ namespace HandyControl.Controls if (Items.Count == 0) return; if (!IsCenter) { - _itemsControl.BeginAnimation(MarginProperty, + ItemsHost.BeginAnimation(MarginProperty, AnimationHelper.CreateAnimation(new Thickness(-_widthList[PageIndex], 0, 0, 0))); } else { - var ctl = (FrameworkElement)Items[PageIndex]; + var ctl = (FrameworkElement)ItemsHost.Children[PageIndex]; var ctlWidth = ctl.DesiredSize.Width; - _itemsControl.BeginAnimation(MarginProperty, + ItemsHost.BeginAnimation(MarginProperty, AnimationHelper.CreateAnimation( new Thickness(-_widthList[PageIndex] + (ActualWidth - ctlWidth) / 2, 0, 0, 0))); } @@ -313,5 +308,149 @@ namespace HandyControl.Controls private void ButtonPrev_OnClick(object sender, RoutedEventArgs e) => PageIndex--; private void ButtonNext_OnClick(object sender, RoutedEventArgs e) => PageIndex++; + + protected override DependencyObject GetContainerForItemOverride() => new CarouselItem(); + + protected override bool IsItemItsOwnContainerOverride(object item) => item is CarouselItem; + + private void ClearItems() + { + ItemsHost?.Children.Clear(); + _entryDic.Clear(); + } + + private void RemoveItem(object item) + { + if (_entryDic.TryGetValue(item, out var entry)) + { + ItemsHost.Children.Remove(entry); + Items.Remove(item); + _entryDic.Remove(item); + } + } + + protected override void Refresh() + { + if (ItemsHost == null) return; + + _entryDic.Clear(); + _isRefresh = true; + + foreach (var item in Items) + { + AddItem(item); + } + + _isRefresh = false; + } + + private void AddItem(object item) => InsertItem(_entryDic.Count, item); + + private void InsertItem(int index, object item) + { + if (ItemsHost == null) + { + Items.Insert(index, item); + _entryDic.Add(item, null); + } + else + { + DependencyObject container; + if (IsItemItsOwnContainerOverride(item)) + { + container = item as DependencyObject; + } + else + { + container = GetContainerForItemOverride(); + PrepareContainerForItemOverride(container, item); + } + + if (container is CarouselItem element) + { + element.Style = ItemContainerStyle; + _entryDic[item] = element; + ItemsHost.Children.Insert(index, element); + + if (IsLoaded && !_isRefresh && _itemsSourceInternal != null) + { + Items.Insert(index, item); + } + } + } + } + + protected override void OnItemsSourceChanged(IEnumerable oldValue, IEnumerable newValue) + { + if (_itemsSourceInternal != null) + { + if (_itemsSourceInternal is INotifyCollectionChanged s) + { + s.CollectionChanged -= InternalCollectionChanged; + } + + Items.Clear(); + ClearItems(); + } + _itemsSourceInternal = newValue; + if (_itemsSourceInternal != null) + { + if (_itemsSourceInternal is INotifyCollectionChanged s) + { + s.CollectionChanged += InternalCollectionChanged; + } + foreach (var item in _itemsSourceInternal) + { + AddItem(item); + } + } + } + + private void InternalCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) + { + if (ItemsHost == null) return; + + if (e.Action == NotifyCollectionChangedAction.Reset) + { + if (_entryDic.Count == 0) return; + ClearItems(); + Items.Clear(); + return; + } + + if (e.OldItems != null) + { + foreach (var item in e.OldItems) + { + RemoveItem(item); + } + } + if (e.NewItems != null) + { + var count = 0; + foreach (var item in e.NewItems) + { + var index = e.NewStartingIndex + count++; + InsertItem(index, item); + } + } + } + + protected override void OnItemsChanged(object sender, NotifyCollectionChangedEventArgs e) + { + if (_itemsSourceInternal != null) return; + + InternalCollectionChanged(sender, e); + } + + protected override void OnItemTemplateChanged(DependencyPropertyChangedEventArgs e) + { + + } + + protected override void OnItemContainerStyleChanged(DependencyPropertyChangedEventArgs e) + { + + } } } \ No newline at end of file diff --git a/src/Shared/HandyControl_Shared/Controls/Carousel/CarouselItem.cs b/src/Shared/HandyControl_Shared/Controls/Carousel/CarouselItem.cs new file mode 100644 index 00000000..6b256f78 --- /dev/null +++ b/src/Shared/HandyControl_Shared/Controls/Carousel/CarouselItem.cs @@ -0,0 +1,9 @@ +using System.Windows.Controls; + +namespace HandyControl.Controls +{ + public class CarouselItem : ContentControl + { + + } +} diff --git a/src/Shared/HandyControl_Shared/Controls/Cover/CoverView/CoverView.cs b/src/Shared/HandyControl_Shared/Controls/Cover/CoverView/CoverView.cs index f1551909..714fcc59 100644 --- a/src/Shared/HandyControl_Shared/Controls/Cover/CoverView/CoverView.cs +++ b/src/Shared/HandyControl_Shared/Controls/Cover/CoverView/CoverView.cs @@ -76,10 +76,7 @@ namespace HandyControl.Controls { base.OnApplyTemplate(); - if (_viewContent.Style == null) - { - _viewContent.Style = CoverViewContentStyle; - } + _viewContent.Style ??= CoverViewContentStyle; if (_selectedItem != null) { @@ -181,9 +178,7 @@ namespace HandyControl.Controls } _isRefresh = false; - GenerateIndex(); - UpdateCoverViewContent(_viewContent.IsOpen); } @@ -338,10 +333,7 @@ namespace HandyControl.Controls { SetBindingForItem(element); element.Style = ItemContainerStyle; - if (element.Header == null) - { - element.Header = item; - } + element.Header ??= item; _entryDic[item] = element; ItemsHost.Children.Insert(index, element); diff --git a/src/Shared/HandyControl_Shared/HandyControl_Shared.projitems b/src/Shared/HandyControl_Shared/HandyControl_Shared.projitems index b447dd89..076eb50b 100644 --- a/src/Shared/HandyControl_Shared/HandyControl_Shared.projitems +++ b/src/Shared/HandyControl_Shared/HandyControl_Shared.projitems @@ -26,6 +26,7 @@ + @@ -143,7 +144,7 @@ - + diff --git a/src/Shared/HandyControl_Shared/Themes/Styles/Carousel.xaml b/src/Shared/HandyControl_Shared/Themes/Styles/Carousel.xaml index d79868a5..a10744b3 100644 --- a/src/Shared/HandyControl_Shared/Themes/Styles/Carousel.xaml +++ b/src/Shared/HandyControl_Shared/Themes/Styles/Carousel.xaml @@ -6,10 +6,94 @@ - - + + + + + + \ No newline at end of file