Files
HandyControl/Net40/HandyControl_Net40/Controls/Cover/CoverView/CoverView.cs
T
2019-02-12 10:23:20 +08:00

217 lines
7.3 KiB
C#

using System.Windows;
using System.Windows.Data;
using HandyControl.Data;
using HandyControl.Tools;
namespace HandyControl.Controls
{
public class CoverView : RegularItemsControl
{
private readonly CoverViewContent _viewContent;
private CoverViewItem _selectedItem;
public CoverView()
{
_viewContent = new CoverViewContent();
AddHandler(SelectableItem.SelectedEvent, new RoutedEventHandler(CoverViewItem_OnSelected));
_viewContent.SetBinding(CoverViewContent.ContentHeightProperty, new Binding(ItemContentHeightProperty.Name) { Source = this });
_viewContent.SetBinding(WidthProperty, new Binding(ActualWidthProperty.Name) { Source = this });
}
private void CoverViewItem_OnSelected(object sender, RoutedEventArgs e)
{
if (e.OriginalSource is CoverViewItem item)
{
if (_selectedItem == null)
{
item.IsSelected = true;
_selectedItem = item;
if (_viewContent != null)
{
_viewContent.Content = item.Content;
UpdateCoverViewContent(true);
}
return;
}
if (!Equals(_selectedItem, item))
{
_selectedItem.IsSelected = false;
item.IsSelected = true;
_selectedItem = item;
if (_viewContent != null)
{
_viewContent.Content = item.Content;
UpdateCoverViewContent(true);
}
return;
}
if (_viewContent != null)
{
_viewContent.Content = null;
UpdateCoverViewContent(false);
}
_selectedItem.IsSelected = false;
_selectedItem = null;
}
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
if (_viewContent.Style == null)
{
_viewContent.Style = CoverViewContentStyle;
}
if (_selectedItem != null)
{
UpdateCoverViewContent(_selectedItem != null);
}
}
protected override DependencyObject GetContainerForItemOverride() => new CoverViewItem();
protected override bool IsItemItsOwnContainerOverride(object item) => item is CoverViewItem;
public static readonly DependencyProperty CoverViewContentStyleProperty = DependencyProperty.Register(
"CoverViewContentStyle", typeof(Style), typeof(CoverView), new PropertyMetadata(default(Style)));
public Style CoverViewContentStyle
{
get => (Style)GetValue(CoverViewContentStyleProperty);
set => SetValue(CoverViewContentStyleProperty, value);
}
internal static readonly DependencyProperty GroupsProperty = DependencyProperty.Register(
"Groups", typeof(int), typeof(CoverView),
new FrameworkPropertyMetadata(ValueBoxes.Int5Box, FrameworkPropertyMetadataOptions.AffectsMeasure,
OnGroupsChanged), IsGroupsValid);
internal static void OnGroupsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is CoverView ctl)
{
ctl.UpdateCoverViewContent(ctl._viewContent.IsOpen);
}
}
private static bool IsGroupsValid(object value)
{
var v = (int)value;
return v >= 1;
}
public int Groups
{
get => (int)GetValue(GroupsProperty);
set => SetValue(GroupsProperty, value);
}
public static readonly DependencyProperty ItemContentHeightProperty = DependencyProperty.Register(
"ItemContentHeight", typeof(double), typeof(CoverView), new PropertyMetadata(ValueBoxes.Double300Box),
value => ValidateHelper.IsInRangeOfPosDouble(value, true));
public double ItemContentHeight
{
get => (double)GetValue(ItemContentHeightProperty);
set => SetValue(ItemContentHeightProperty, value);
}
public static readonly DependencyProperty ItemContentHeightFixedProperty = DependencyProperty.Register(
"ItemContentHeightFixed", typeof(bool), typeof(CoverView), new PropertyMetadata(ValueBoxes.TrueBox));
public bool ItemContentHeightFixed
{
get => (bool)GetValue(ItemContentHeightFixedProperty);
set => SetValue(ItemContentHeightFixedProperty, value);
}
protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
{
base.OnRenderSizeChanged(sizeInfo);
Groups = (int)(sizeInfo.NewSize.Width / (ItemWidth + ItemMargin.Left + ItemMargin.Right));
}
protected override void Refresh()
{
if (ItemsHost == null) return;
ItemsHost.Children.Clear();
var index = 0;
foreach (var item in Items)
{
DependencyObject container;
if (IsItemItsOwnContainerOverride(item))
{
container = item as DependencyObject;
}
else
{
container = GetContainerForItemOverride();
PrepareContainerForItemOverride(container, item);
}
if (container is CoverViewItem element)
{
element.Index = index++;
element.Style = ItemContainerStyle;
ItemsHost.Children.Add(element);
}
}
}
/// <summary>
/// 更新内容视图
/// </summary>
private void UpdateCoverViewContent(bool isOpen)
{
if (_selectedItem == null) return;
ItemsHost.Children.Remove(_viewContent);
if (!ItemContentHeightFixed)
{
_viewContent.ManualHeight = 0;
if (_viewContent.Content is FrameworkElement element)
{
element.VerticalAlignment = VerticalAlignment.Top;
element.Arrange(new Rect(new Size(double.MaxValue, double.MaxValue)));
_viewContent.ManualHeight = element.ActualHeight;
}
}
var total = Items.Count + 1;
var totalRow = total / Groups + (total % Groups > 0 ? 1 : 0);
if (total <= Groups)
{
ItemsHost.Children.Add(_viewContent);
}
else
{
var row = _selectedItem.Index / Groups + 1;
if (row == totalRow)
{
ItemsHost.Children.Add(_viewContent);
}
else
{
ItemsHost.Children.Insert(row * Groups, _viewContent);
}
}
_viewContent.UpdatePosition(_selectedItem.Index, Groups, _selectedItem.DesiredSize.Width);
if (_viewContent.CanSwitch)
{
_viewContent.IsOpen = isOpen;
}
}
}
}