Merge branch 'master' into pr/75

This commit is contained in:
NaBian committed 2019-05-13 19:42:29 +08:00
commit 9b0205a030
125 files changed
+5048 -832

No files matched your search

@@ -0,0 +1,16 @@
using System.Windows;
namespace HandyControl.Controls
{
public class HeaderedSimpleItemsControl : SimpleItemsControl
{
public static readonly DependencyProperty HeaderProperty = DependencyProperty.Register(
"Header", typeof(object), typeof(HeaderedSimpleItemsControl), new PropertyMetadata(default(object)));
public object Header
{
get => GetValue(HeaderProperty);
set => SetValue(HeaderProperty, value);
}
}
}
@@ -5,6 +5,7 @@ using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Markup;
using HandyControl.Data;
namespace HandyControl.Controls
{
@@ -33,7 +34,14 @@ namespace HandyControl.Controls
public SimpleItemsControl()
{
var items = new ObservableCollection<object>();
items.CollectionChanged += OnItemsChanged;
items.CollectionChanged += (s, e) =>
{
if (e.NewItems != null && e.NewItems.Count > 0)
{
SetValue(HasItemsPropertyKey, true);
}
OnItemsChanged(s, e);
};
Items = items;
}
@@ -118,6 +126,14 @@ namespace HandyControl.Controls
protected virtual void OnItemContainerStyleChanged(DependencyPropertyChangedEventArgs e) => Refresh();
internal static readonly DependencyPropertyKey HasItemsPropertyKey =
DependencyProperty.RegisterReadOnly(nameof(HasItems), typeof(bool), typeof(SimpleItemsControl),
new PropertyMetadata(ValueBoxes.FalseBox));
public static readonly DependencyProperty HasItemsProperty = HasItemsPropertyKey.DependencyProperty;
public bool HasItems => (bool) GetValue(HasItemsProperty);
protected virtual void Refresh()
{
if (ItemsHost == null) return;
@@ -45,9 +45,9 @@ namespace HandyControl.Controls
{
return 0;
}
if (v >= ctl._uriList.Count)
if (v >= ctl._contentDic.Count)
{
return ctl._uriList.Count - 1;
return ctl._contentDic.Count - 1;
}
return v;
}
@@ -65,9 +65,9 @@ namespace HandyControl.Controls
"Loop", typeof(bool), typeof(CoverFlow), new PropertyMetadata(ValueBoxes.FalseBox));
/// <summary>
/// 存储所有的资源标识符
/// 存储所有的内容
/// </summary>
private readonly Dictionary<int, Uri> _uriList = new Dictionary<int, Uri>();
private readonly Dictionary<int, object> _contentDic = new Dictionary<int, object>();
/// <summary>
/// 当前在显示范围内的项
@@ -154,12 +154,12 @@ namespace HandyControl.Controls
/// <summary>
/// 批量添加资源
/// </summary>
/// <param name="uriList"></param>
public void AddRange(List<Uri> uriList)
/// <param name="contentList"></param>
public void AddRange(IEnumerable<object> contentList)
{
foreach (var uri in uriList)
foreach (var content in contentList)
{
_uriList.Add(_uriList.Count, uri);
_contentDic.Add(_contentDic.Count, content);
}
}
@@ -167,13 +167,13 @@ namespace HandyControl.Controls
/// 添加一项资源
/// </summary>
/// <param name="uriString"></param>
public void Add(string uriString) => _uriList.Add(_uriList.Count, new Uri(uriString));
public void Add(string uriString) => _contentDic.Add(_contentDic.Count, new Uri(uriString));
/// <summary>
/// 添加一项资源
/// </summary>
/// <param name="uri"></param>
public void Add(Uri uri) => _uriList.Add(_uriList.Count, uri);
public void Add(Uri uri) => _contentDic.Add(_contentDic.Count, uri);
/// <summary>
/// 跳转
@@ -187,13 +187,15 @@ namespace HandyControl.Controls
if (e.Delta < 0)
{
var index = PageIndex + 1;
PageIndex = index >= _uriList.Count ? (Loop ? 0 : _uriList.Count - 1) : index;
PageIndex = index >= _contentDic.Count ? Loop ? 0 : _contentDic.Count - 1 : index;
}
else
{
var index = PageIndex - 1;
PageIndex = index < 0 ? (Loop ? _uriList.Count - 1 : 0) : index;
PageIndex = index < 0 ? Loop ? _contentDic.Count - 1 : 0 : index;
}
e.Handled = true;
}
/// <summary>
@@ -271,7 +273,7 @@ namespace HandyControl.Controls
private void UpdateShowRange()
{
var newFirstShowIndex = Math.Max(PageIndex - MaxShowCountHalf, 0);
var newLastShowIndex = Math.Min(PageIndex + MaxShowCountHalf, _uriList.Count - 1);
var newLastShowIndex = Math.Min(PageIndex + MaxShowCountHalf, _contentDic.Count - 1);
if (_firstShowIndex < newFirstShowIndex)
{
@@ -292,7 +294,7 @@ namespace HandyControl.Controls
{
if (!_itemShowList.ContainsKey(i))
{
var cover = new CoverFlowItem(i, PageIndex, BitmapFrame.Create(_uriList[i]));
var cover = CreateCoverFlowItem(i, _contentDic[i]);
_itemShowList[i] = cover;
_visualParent.Children.Add(cover);
}
@@ -301,5 +303,21 @@ namespace HandyControl.Controls
_firstShowIndex = newFirstShowIndex;
_lastShowIndex = newLastShowIndex;
}
private CoverFlowItem CreateCoverFlowItem(int index, object content)
{
if (content is Uri uri)
{
return new CoverFlowItem(index, PageIndex, new Image
{
Source = BitmapFrame.Create(uri)
});
}
return new CoverFlowItem(index, PageIndex, new ContentControl
{
Content = content
});
}
}
}
@@ -18,14 +18,15 @@ namespace HandyControl.Controls
private readonly Model3DGroup _model3DGroup;
private readonly ImageSource _source;
private readonly UIElement _uiElement;
internal int Index { get; set; }
public CoverFlowItem(int itemIndex, int currentIndex, ImageSource source)
public CoverFlowItem(int itemIndex, int currentIndex, UIElement element)
{
Index = itemIndex;
_source = source;
_uiElement = element;
_uiElement.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
_rotation3D = new AxisAngleRotation3D(new Vector3D(0, 1, 0), GetAngleByPos(currentIndex));
_transform3D = new TranslateTransform3D(GetXByPos(currentIndex), 0, GetZByPos(currentIndex));
@@ -35,7 +36,7 @@ namespace HandyControl.Controls
transformGroup.Children.Add(_transform3D);
_model3DGroup = new Model3DGroup();
_model3DGroup.Children.Add(new GeometryModel3D(CreateItemGeometry(), new DiffuseMaterial(new ImageBrush(_source))));
_model3DGroup.Children.Add(new GeometryModel3D(CreateItemGeometry(), new DiffuseMaterial(new VisualBrush(element))));
_model3DGroup.Transform = transformGroup;
Content = _model3DGroup;
@@ -103,8 +104,8 @@ namespace HandyControl.Controls
/// <returns></returns>
private Geometry3D CreateItemGeometry()
{
var sx = _source.Width > _source.Height ? 0 : 1 - _source.Width / _source.Height;
var sy = _source.Width < _source.Height ? 0 : 1 - _source.Height / _source.Width;
var sx = _uiElement.DesiredSize.Width > _uiElement.DesiredSize.Height ? 0 : 1 - _uiElement.DesiredSize.Width / _uiElement.DesiredSize.Height;
var sy = _uiElement.DesiredSize.Width < _uiElement.DesiredSize.Height ? 0 : 1 - _uiElement.DesiredSize.Height / _uiElement.DesiredSize.Width;
var p0 = new Point3D(-1 + sx, -1 + sy, 0);
var p1 = new Point3D(1 - sx, -1 + sy, 0);
@@ -0,0 +1,79 @@
using System.Windows;
using System.Windows.Controls;
using HandyControl.Data;
using HandyControl.Tools.Extension;
namespace HandyControl.Controls
{
public class Col : ContentControl
{
public static readonly DependencyProperty LayoutProperty = DependencyProperty.Register(
"Layout", typeof(ColLayout), typeof(Col), new PropertyMetadata(default(ColLayout)));
public ColLayout Layout
{
get => (ColLayout)GetValue(LayoutProperty);
set => SetValue(LayoutProperty, value);
}
public static readonly DependencyProperty OffsetProperty = DependencyProperty.Register(
"Offset", typeof(int), typeof(Col), new PropertyMetadata(ValueBoxes.Int0Box));
public int Offset
{
get => (int)GetValue(OffsetProperty);
set => SetValue(OffsetProperty, value);
}
public static readonly DependencyProperty SpanProperty = DependencyProperty.Register(
"Span", typeof(int), typeof(Col), new PropertyMetadata(24), OnSpanValidate);
private static bool OnSpanValidate(object value)
{
var v = (int)value;
return v >= 1 || v <= 24;
}
public int Span
{
get => (int) GetValue(SpanProperty);
set => SetValue(SpanProperty, value);
}
internal int GetLayoutCellCount(ColLayoutStatus status)
{
var result = 0;
if (Layout != null)
{
switch (status)
{
case ColLayoutStatus.Xs:
result = Layout.Xs;
break;
case ColLayoutStatus.Sm:
result = Layout.Sm;
break;
case ColLayoutStatus.Md:
result = Layout.Md;
break;
case ColLayoutStatus.Lg:
result = Layout.Lg;
break;
case ColLayoutStatus.Xl:
result = Layout.Xl;
break;
case ColLayoutStatus.Xxl:
result = Layout.Xxl;
break;
}
}
else
{
result = Span;
}
return result;
}
}
}
@@ -0,0 +1,102 @@
using HandyControl.Tools.Extension;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using HandyControl.Data;
using HandyControl.Tools;
namespace HandyControl.Controls
{
public class Row : Panel
{
private ColLayoutStatus _layoutStatus;
private double _maxChildDesiredHeight;
public static readonly DependencyProperty GutterProperty = DependencyProperty.Register(
"Gutter", typeof(double), typeof(Row), new PropertyMetadata(ValueBoxes.Double0Box, null, OnGutterCoerce), OnGutterValidate);
private static object OnGutterCoerce(DependencyObject d, object basevalue) => OnGutterValidate(basevalue) ? basevalue : .0;
private static bool OnGutterValidate(object value) => ValidateHelper.IsInRangeOfPosDouble(value, true);
public double Gutter
{
get => (double)GetValue(GutterProperty);
set => SetValue(GutterProperty, value);
}
protected override Size MeasureOverride(Size constraint)
{
var totalCellCount = 0;
var totalRowCount = 1;
var gutterHalf = Gutter / 2;
foreach (var child in InternalChildren.OfType<Col>())
{
child.Margin = new Thickness(gutterHalf);
child.Measure(constraint);
var childDesiredSize = child.DesiredSize;
if (_maxChildDesiredHeight < childDesiredSize.Height)
{
_maxChildDesiredHeight = childDesiredSize.Height;
}
}
var itemWidth = constraint.Width / ColLayout.ColMaxCellCount;
var childBounds = new Rect(-gutterHalf, -gutterHalf, 0, _maxChildDesiredHeight);
_layoutStatus = ColLayout.GetLayoutStatus(constraint.Width);
foreach (var child in InternalChildren.OfType<Col>())
{
var cellCount = child.GetLayoutCellCount(_layoutStatus);
totalCellCount += cellCount;
if (totalCellCount > ColLayout.ColMaxCellCount)
{
childBounds.X = -gutterHalf;
childBounds.Y += _maxChildDesiredHeight;
totalCellCount = cellCount;
totalRowCount++;
}
var childWidth = cellCount * itemWidth;
childBounds.Width = childWidth;
childBounds.X += childWidth + child.Offset * itemWidth;
}
return new Size(0, _maxChildDesiredHeight * totalRowCount - Gutter);
}
protected override Size ArrangeOverride(Size finalSize)
{
var totalCellCount = 0;
var gutterHalf = Gutter / 2;
var itemWidth = (finalSize.Width + Gutter) / ColLayout.ColMaxCellCount;
var childBounds = new Rect(-gutterHalf, -gutterHalf, 0, _maxChildDesiredHeight);
_layoutStatus = ColLayout.GetLayoutStatus(finalSize.Width);
foreach (var child in InternalChildren.OfType<Col>())
{
var cellCount = child.GetLayoutCellCount(_layoutStatus);
totalCellCount += cellCount;
var childWidth = cellCount * itemWidth;
childBounds.Width = childWidth;
childBounds.X += child.Offset * itemWidth;
if (totalCellCount > ColLayout.ColMaxCellCount)
{
childBounds.X = -gutterHalf;
childBounds.Y += _maxChildDesiredHeight;
totalCellCount = cellCount;
}
child.Arrange(childBounds);
childBounds.X += childWidth;
}
return finalSize;
}
}
}
@@ -1,15 +1,44 @@
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Input;
#if netle40
using System.Windows.Threading;
#endif
using HandyControl.Data;
using HandyControl.Interactivity;
namespace HandyControl.Controls
{
/// <inheritdoc cref="IDataInput" />
[TemplatePart(Name = AutoCompletePanel, Type = typeof(Panel))]
[TemplatePart(Name = EditableTextBox, Type = typeof(System.Windows.Controls.TextBox))]
[TemplatePart(Name = AutoPopupAutoComplete, Type = typeof(Popup))]
public class ComboBox : System.Windows.Controls.ComboBox, IDataInput
{
#if netle40
private string _searchText;
private DispatcherTimer _autoCompleteTimer;
#endif
private bool _isAutoCompleteAction = true;
private Panel _autoCompletePanel;
private System.Windows.Controls.TextBox _editableTextBox;
private Popup _autoPopupAutoComplete;
private const string AutoCompletePanel = "PART_AutoCompletePanel";
private const string AutoPopupAutoComplete = "PART_Popup_AutoComplete";
private const string EditableTextBox = "PART_EditableTextBox";
public ComboBox()
{
CommandBindings.Add(new CommandBinding(ControlCommands.Clear, (s, e) =>
@@ -21,23 +50,125 @@ namespace HandyControl.Controls
}));
}
protected override void OnSelectionChanged(SelectionChangedEventArgs e)
public override void OnApplyTemplate()
{
if (_editableTextBox != null)
{
BindingOperations.ClearBinding(_editableTextBox, System.Windows.Controls.TextBox.TextProperty);
_editableTextBox.GotFocus -= EditableTextBox_GotFocus;
_editableTextBox.LostFocus -= EditableTextBox_LostFocus;
}
base.OnApplyTemplate();
if (IsEditable)
{
_editableTextBox = GetTemplateChild(EditableTextBox) as System.Windows.Controls.TextBox;
if (_editableTextBox != null)
{
_editableTextBox.TextChanged += EditableTextBox_TextChanged;
if (AutoComplete)
{
#if netle40
_autoCompleteTimer = new DispatcherTimer
{
Interval = TimeSpan.FromMilliseconds(500)
};
_autoCompleteTimer.Tick += AutoCompleteTimer_Tick;
#endif
_autoPopupAutoComplete = GetTemplateChild(AutoPopupAutoComplete) as Popup;
_autoCompletePanel = GetTemplateChild(AutoCompletePanel) as Panel;
_editableTextBox.SetBinding(System.Windows.Controls.TextBox.TextProperty, new Binding(SearchTextProperty.Name)
{
UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged,
Mode = BindingMode.OneWayToSource,
#if !netle40
Delay = 500,
#endif
Source = this
});
_editableTextBox.GotFocus += EditableTextBox_GotFocus;
_editableTextBox.LostFocus += EditableTextBox_LostFocus;
}
}
}
}
#if netle40
private void AutoCompleteTimer_Tick(object sender, EventArgs e)
{
UpdateSearchItems(_searchText);
_autoCompleteTimer.Stop();
}
#endif
private void EditableTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
base.OnSelectionChanged(e);
VerifyData();
}
private void EditableTextBox_LostFocus(object sender, RoutedEventArgs e)
{
if (_autoPopupAutoComplete != null)
{
_autoPopupAutoComplete.IsOpen = false;
}
}
#if !netle40
protected override void OnDropDownClosed(EventArgs e)
{
base.OnDropDownClosed(e);
_isAutoCompleteAction = false;
}
#endif
private void EditableTextBox_GotFocus(object sender, RoutedEventArgs e)
{
if (_autoPopupAutoComplete != null && _editableTextBox != null &&
!string.IsNullOrEmpty(_editableTextBox.Text))
{
_autoPopupAutoComplete.IsOpen = true;
}
}
protected override void OnSelectionChanged(SelectionChangedEventArgs e)
{
_isAutoCompleteAction = false;
base.OnSelectionChanged(e);
VerifyData();
#if netle40
_isAutoCompleteAction = true;
#endif
}
/// <summary>
/// 数据验证委托
/// </summary>
public Func<string, OperationResult<bool>> VerifyFunc { get; set; }
/// <summary>
/// 数据搜索委托
/// </summary>
public Func<ItemCollection, object, IEnumerable<object>> SearchFunc { get; set; }
/// <summary>
/// 数据是否错误
/// </summary>
public static readonly DependencyProperty IsErrorProperty = DependencyProperty.Register(
"IsError", typeof(bool), typeof(ComboBox), new PropertyMetadata(ValueBoxes.FalseBox));
/// <summary>
/// 数据是否错误
/// </summary>
public bool IsError
{
get => (bool) GetValue(IsErrorProperty);
get => (bool)GetValue(IsErrorProperty);
set => SetValue(IsErrorProperty, value);
}
@@ -47,12 +178,18 @@ namespace HandyControl.Controls
public static readonly DependencyProperty ErrorStrProperty = DependencyProperty.Register(
"ErrorStr", typeof(string), typeof(ComboBox), new PropertyMetadata(default(string)));
/// <summary>
/// 错误提示
/// </summary>
public string ErrorStr
{
get => (string) GetValue(ErrorStrProperty);
get => (string)GetValue(ErrorStrProperty);
set => SetValue(ErrorStrProperty, value);
}
/// <summary>
/// 文本类型
/// </summary>
public static readonly DependencyPropertyKey TextTypePropertyKey =
DependencyProperty.RegisterReadOnly("TextType", typeof(TextType), typeof(ComboBox),
new PropertyMetadata(default(TextType)));
@@ -62,9 +199,12 @@ namespace HandyControl.Controls
/// </summary>
public static readonly DependencyProperty TextTypeProperty = TextTypePropertyKey.DependencyProperty;
/// <summary>
/// 文本类型
/// </summary>
public TextType TextType
{
get => (TextType) GetValue(TextTypeProperty);
get => (TextType)GetValue(TextTypeProperty);
set => SetValue(TextTypeProperty, value);
}
@@ -74,23 +214,151 @@ namespace HandyControl.Controls
public static readonly DependencyProperty ShowClearButtonProperty = DependencyProperty.Register(
"ShowClearButton", typeof(bool), typeof(ComboBox), new PropertyMetadata(ValueBoxes.FalseBox));
/// <summary>
/// 是否显示清除按钮
/// </summary>
public bool ShowClearButton
{
get => (bool) GetValue(ShowClearButtonProperty);
get => (bool)GetValue(ShowClearButtonProperty);
set => SetValue(ShowClearButtonProperty, value);
}
/// <summary>
/// 是否自动完成输入
/// </summary>
public static readonly DependencyProperty AutoCompleteProperty = DependencyProperty.Register(
"AutoComplete", typeof(bool), typeof(ComboBox), new PropertyMetadata(ValueBoxes.FalseBox, OnAutoCompleteChanged));
private static void OnAutoCompleteChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var ctl = (ComboBox)d;
if (ctl._editableTextBox != null)
{
ctl.UpdateSearchItems(ctl._editableTextBox.Text);
}
}
/// <summary>
/// 更新搜索的项目
/// </summary>
/// <param name="key"></param>
private void UpdateSearchItems(string key)
{
if (_editableTextBox != null && _autoPopupAutoComplete != null)
{
_autoPopupAutoComplete.IsOpen = !string.IsNullOrEmpty(key);
_autoCompletePanel.Children.Clear();
if (SearchFunc == null)
{
if (!string.IsNullOrEmpty(key))
{
foreach (var item in Items)
{
var content = item?.ToString();
if (content == null) continue;
if (!content.Contains(key)) continue;
_autoCompletePanel.Children.Add(CreateSearchItem(item));
}
}
}
else
{
foreach (var item in SearchFunc.Invoke(Items, key))
{
_autoCompletePanel.Children.Add(CreateSearchItem(item));
}
}
}
}
private ComboBoxItem CreateSearchItem(object content)
{
var item = new ComboBoxItem
{
Content = content,
Style = ItemContainerStyle,
ContentTemplate = ItemTemplate
};
item.PreviewMouseLeftButtonDown += AutoCompleteItem_PreviewMouseLeftButtonDown;
return item;
}
private void AutoCompleteItem_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (sender is ComboBoxItem comboBoxItem)
{
if (_autoPopupAutoComplete != null)
{
_autoPopupAutoComplete.IsOpen = false;
}
_isAutoCompleteAction = false;
SelectedValue = comboBoxItem.Content;
}
}
/// <summary>
/// 搜索文本
/// </summary>
internal static readonly DependencyProperty SearchTextProperty = DependencyProperty.Register(
"SearchText", typeof(string), typeof(ComboBox), new PropertyMetadata(default(string), OnSearchTextChanged));
private static void OnSearchTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var ctl = (ComboBox)d;
if (ctl._isAutoCompleteAction)
{
#if netle40
ctl._searchText = e.NewValue as string;
ctl._autoCompleteTimer.Stop();
ctl._autoCompleteTimer.Start();
#else
ctl.UpdateSearchItems(e.NewValue as string);
#endif
}
ctl._isAutoCompleteAction = true;
}
/// <summary>
/// 搜索文本
/// </summary>
internal string SearchText
{
get => (string)GetValue(SearchTextProperty);
set => SetValue(SearchTextProperty, value);
}
/// <summary>
/// 是否自动完成输入
/// </summary>
public bool AutoComplete
{
get => (bool)GetValue(AutoCompleteProperty);
set => SetValue(AutoCompleteProperty, value);
}
/// <summary>
/// 验证数据
/// </summary>
/// <returns></returns>
public virtual bool VerifyData()
{
OperationResult<bool> result;
var value = _editableTextBox == null ? Text : _editableTextBox.Text;
if (VerifyFunc != null)
{
result = VerifyFunc.Invoke(Text);
result = VerifyFunc.Invoke(value);
}
else
{
if (!string.IsNullOrEmpty(Text))
if (!string.IsNullOrEmpty(value))
{
result = OperationResult.Success();
}
@@ -99,15 +99,6 @@ namespace HandyControl.Controls
set => SetValue(DateTimeFormatProperty, value);
}
public static readonly DependencyProperty ClockStyleProperty = DependencyProperty.Register(
"ClockStyle", typeof(Style), typeof(DateTimePicker), new PropertyMetadata(default(Style)));
public Style ClockStyle
{
get => (Style) GetValue(ClockStyleProperty);
set => SetValue(ClockStyleProperty, value);
}
public static readonly DependencyProperty CalendarStyleProperty = DependencyProperty.Register(
"CalendarStyle", typeof(Style), typeof(DateTimePicker), new PropertyMetadata(default(Style)));
@@ -152,7 +152,7 @@ namespace HandyControl.Controls
/// </summary>
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(
"Value", typeof(double), typeof(NumericUpDown),
new FrameworkPropertyMetadata(default(double), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
new FrameworkPropertyMetadata(ValueBoxes.Double0Box, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
OnValueChanged, CoerceValue), ArithmeticHelper.IsValidDoubleValue);
private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
@@ -204,7 +204,7 @@ namespace HandyControl.Controls
/// 最大值
/// </summary>
public static readonly DependencyProperty MaximumProperty = DependencyProperty.Register(
"Maximum", typeof(double), typeof(NumericUpDown), new PropertyMetadata(100.0, OnMaximumChanged, CoerceMaximum), ArithmeticHelper.IsValidDoubleValue);
"Maximum", typeof(double), typeof(NumericUpDown), new PropertyMetadata(double.MaxValue, OnMaximumChanged, CoerceMaximum), ArithmeticHelper.IsValidDoubleValue);
private static void OnMaximumChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
@@ -34,8 +34,6 @@ namespace HandyControl.Controls
#region Data
private Clock _clock;
private string _defaultText;
private ButtonBase _dropDownButton;
@@ -79,7 +77,7 @@ namespace HandyControl.Controls
public TimePicker()
{
InitClock();
Clock = new Clock();
CommandBindings.Add(new CommandBinding(ControlCommands.Clear, (s, e) =>
{
ClearValue(SelectedTimeProperty);
@@ -103,18 +101,6 @@ namespace HandyControl.Controls
#endregion TimeFormat
#region ClockStyle
public Style ClockStyle
{
get => (Style)GetValue(ClockStyleProperty);
set => SetValue(ClockStyleProperty, value);
}
public static readonly DependencyProperty ClockStyleProperty = DependencyProperty.Register("ClockStyle", typeof(Style), typeof(TimePicker));
#endregion CalendarStyle
#region DisplayTime
public DateTime DisplayTime
@@ -133,8 +119,8 @@ namespace HandyControl.Controls
private static object CoerceDisplayTime(DependencyObject d, object value)
{
var dp = (TimePicker)d;
dp._clock.DisplayTime = (DateTime)value;
return dp._clock.DisplayTime;
dp.Clock.DisplayTime = (DateTime)value;
return dp.Clock.DisplayTime;
}
#endregion DisplayTime
@@ -170,7 +156,7 @@ namespace HandyControl.Controls
dp.Dispatcher.BeginInvoke(DispatcherPriority.Input, (Action)delegate
{
dp._clock.Focus();
dp.Clock.Focus();
});
}
}
@@ -212,8 +198,8 @@ namespace HandyControl.Controls
private static object CoerceSelectedTime(DependencyObject d, object value)
{
var dp = (TimePicker)d;
dp._clock.SelectedTime = (DateTime?)value;
return dp._clock.SelectedTime;
dp.Clock.SelectedTime = (DateTime?)value;
return dp.Clock.SelectedTime;
}
#endregion SelectedDate
@@ -306,6 +292,35 @@ namespace HandyControl.Controls
set => SetValue(ShowClearButtonProperty, value);
}
public static readonly DependencyProperty ClockProperty = DependencyProperty.Register(
"Clock", typeof(ClockBase), typeof(TimePicker), new FrameworkPropertyMetadata(default(Clock), FrameworkPropertyMetadataOptions.NotDataBindable, OnClockChanged));
private static void OnClockChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var ctl = (TimePicker) d;
var oldClock = e.OldValue as ClockBase;
var newClock = e.NewValue as ClockBase;
if (oldClock != null)
{
oldClock.SelectedTimeChanged -= ctl.Clock_SelectedTimeChanged;
oldClock.Confirmed -= ctl.Clock_Confirmed;
}
if (newClock != null)
{
newClock.ShowConfirmButton = true;
newClock.SelectedTimeChanged += ctl.Clock_SelectedTimeChanged;
newClock.Confirmed += ctl.Clock_Confirmed;
}
}
public ClockBase Clock
{
get => (ClockBase) GetValue(ClockProperty);
set => SetValue(ClockProperty, value);
}
#endregion Public Properties
#region Public Methods
@@ -374,7 +389,7 @@ namespace HandyControl.Controls
_popUp.PreviewMouseLeftButtonDown += PopUp_PreviewMouseLeftButtonDown;
_popUp.Opened += PopUp_Opened;
_popUp.Closed += PopUp_Closed;
_popUp.Child = _clock;
_popUp.Child = Clock;
if (IsDropDownOpen)
{
@@ -439,20 +454,7 @@ namespace HandyControl.Controls
throw new Exception();
}
private void InitClock()
{
_clock = new Clock
{
ShowConfirmButton = true
};
_clock.SelectedTimeChanged += Clock_SelectedTimeChanged;
_clock.Confirmed += Clock_Confirmed;
}
private void TextBox_LostFocus(object sender, RoutedEventArgs e)
{
SetSelectedTime();
}
private void TextBox_LostFocus(object sender, RoutedEventArgs e) => SetSelectedTime();
private void SetIsHandlerSuspended(DependencyProperty property, bool value)
{
@@ -560,7 +562,7 @@ namespace HandyControl.Controls
SetCurrentValue(IsDropDownOpenProperty, ValueBoxes.TrueBox);
}
_clock?.MoveFocus(new TraversalRequest(FocusNavigationDirection.First));
Clock?.MoveFocus(new TraversalRequest(FocusNavigationDirection.First));
OnClockOpened(new RoutedEventArgs());
}
@@ -572,7 +574,7 @@ namespace HandyControl.Controls
SetCurrentValue(IsDropDownOpenProperty, ValueBoxes.FalseBox);
}
if (_clock.IsKeyboardFocusWithin)
if (Clock.IsKeyboardFocusWithin)
{
MoveFocus(new TraversalRequest(FocusNavigationDirection.First));
}
@@ -15,7 +15,7 @@ namespace HandyControl.Controls
private bool _isLoaded;
/// <summary>
/// 故事版
/// 故事板
/// </summary>
private Storyboard _storyboard;
@@ -1,4 +1,6 @@
using System.Windows;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
@@ -12,6 +14,8 @@ namespace HandyControl.Controls
{
private Adorner _container;
private static readonly Dictionary<string, System.Windows.Window> WindowDic = new Dictionary<string, System.Windows.Window>();
public static readonly DependencyProperty IsClosedProperty = DependencyProperty.Register(
"IsClosed", typeof(bool), typeof(Dialog), new PropertyMetadata(ValueBoxes.FalseBox));
@@ -21,21 +25,94 @@ namespace HandyControl.Controls
internal set => SetValue(IsClosedProperty, value);
}
public static readonly DependencyProperty TokenProperty = DependencyProperty.RegisterAttached(
"Token", typeof(string), typeof(Dialog), new PropertyMetadata(default(string), OnTokenChanged));
private static void OnTokenChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is System.Windows.Window window)
{
if (e.NewValue == null)
{
Unregister(window);
}
else
{
Register(e.NewValue.ToString(), window);
}
}
}
public static void SetToken(DependencyObject element, string value)
=> element.SetValue(TokenProperty, value);
public static string GetToken(DependencyObject element)
=> (string) element.GetValue(TokenProperty);
public Dialog()
{
CommandBindings.Add(new CommandBinding(ControlCommands.Close, (s, e) => Close()));
}
public static Dialog Show<T>() where T : new() => Show(new T());
public static void Register(string token, System.Windows.Window window)
{
if (string.IsNullOrEmpty(token) || window == null) return;
WindowDic[token] = window;
}
public static Dialog Show(object content)
public static void Unregister(string token, System.Windows.Window window)
{
if (string.IsNullOrEmpty(token) || window == null) return;
if (WindowDic.ContainsKey(token))
{
if (ReferenceEquals(WindowDic[token], window))
{
WindowDic.Remove(token);
}
}
}
public static void Unregister(System.Windows.Window window)
{
if (window == null) return;
var first = WindowDic.FirstOrDefault(item => ReferenceEquals(window, item.Value));
if (!string.IsNullOrEmpty(first.Key))
{
WindowDic.Remove(first.Key);
}
}
public static void Unregister(string token)
{
if (string.IsNullOrEmpty(token)) return;
if (WindowDic.ContainsKey(token))
{
WindowDic.Remove(token);
}
}
public static Dialog Show<T>(string token = "") where T : new() => Show(new T(), token);
public static Dialog Show(object content, string token = "")
{
var dialog = new Dialog
{
Content = content
};
var window = VisualHelper.GetActiveWindow();
System.Windows.Window window;
if (string.IsNullOrEmpty(token))
{
window = VisualHelper.GetActiveWindow();
}
else
{
WindowDic.TryGetValue(token, out window);
}
if (window != null)
{
var decorator = VisualHelper.GetChild<AdornerDecorator>(window);
@@ -62,9 +139,23 @@ namespace HandyControl.Controls
return dialog;
}
public void Close()
public void Close(string token = "")
{
if (!string.IsNullOrEmpty(token))
{
if (WindowDic.TryGetValue(token, out var window))
{
Close(window);
}
}
else
{
Close(VisualHelper.GetActiveWindow());
}
}
private void Close(System.Windows.Window window)
{
var window = VisualHelper.GetActiveWindow();
if (window != null)
{
var decorator = VisualHelper.GetChild<AdornerDecorator>(window);
@@ -98,6 +98,19 @@ namespace HandyControl.Controls
}
}
public static void Unregister(string token)
{
if (string.IsNullOrEmpty(token)) return;
if (PanelDic.ContainsKey(token))
{
var panel = PanelDic[token];
PanelDic.Remove(token);
panel.ContextMenu = null;
panel.SetCurrentValue(PanelElement.FluidMoveBehaviorProperty, DependencyProperty.UnsetValue);
}
}
protected override void OnMouseEnter(MouseEventArgs e)
{
base.OnMouseEnter(e);
@@ -114,7 +114,8 @@ namespace HandyControl.Controls
_isRunning = false;
};
_isRunning = true;
BeginAnimation(CurrentVerticalOffsetProperty, animation);
BeginAnimation(CurrentVerticalOffsetProperty, animation, HandoffBehavior.Compose);
}
internal void ScrollToHorizontalOffsetInternal(double offset, double milliseconds = 500)
@@ -131,7 +132,8 @@ namespace HandyControl.Controls
_isRunning = false;
};
_isRunning = true;
BeginAnimation(CurrentHorizontalOffsetProperty, animation);
BeginAnimation(CurrentHorizontalOffsetProperty, animation, HandoffBehavior.Compose);
}
protected override HitTestResult HitTestCore(PointHitTestParameters hitTestParameters) =>
@@ -150,7 +152,7 @@ namespace HandyControl.Controls
public static bool GetIsEnableInertia(DependencyObject element)
{
return (bool) element.GetValue(IsEnableInertiaProperty);
return (bool)element.GetValue(IsEnableInertiaProperty);
}
/// <summary>
@@ -158,7 +160,7 @@ namespace HandyControl.Controls
/// </summary>
public bool IsEnableInertia
{
get => (bool)GetValue(IsEnableInertiaProperty);
get => (bool) GetValue(IsEnableInertiaProperty);
set => SetValue(IsEnableInertiaProperty, value);
}
@@ -173,7 +175,7 @@ namespace HandyControl.Controls
/// </summary>
public bool IsPenetrating
{
get => (bool)GetValue(IsPenetratingProperty);
get => (bool) GetValue(IsPenetratingProperty);
set => SetValue(IsPenetratingProperty, value);
}
@@ -190,7 +192,7 @@ namespace HandyControl.Controls
/// <summary>
/// 当前垂直滚动偏移
/// </summary>
private static readonly DependencyProperty CurrentVerticalOffsetProperty = DependencyProperty.Register(
internal static readonly DependencyProperty CurrentVerticalOffsetProperty = DependencyProperty.Register(
"CurrentVerticalOffset", typeof(double), typeof(ScrollViewer), new PropertyMetadata(ValueBoxes.Double0Box, OnCurrentVerticalOffsetChanged));
private static void OnCurrentVerticalOffsetChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
@@ -204,7 +206,7 @@ namespace HandyControl.Controls
/// <summary>
/// 当前垂直滚动偏移
/// </summary>
private double CurrentVerticalOffset
internal double CurrentVerticalOffset
{
// ReSharper disable once UnusedMember.Local
get => (double) GetValue(CurrentVerticalOffsetProperty);
@@ -214,7 +216,7 @@ namespace HandyControl.Controls
/// <summary>
/// 当前水平滚动偏移
/// </summary>
public static readonly DependencyProperty CurrentHorizontalOffsetProperty = DependencyProperty.Register(
internal static readonly DependencyProperty CurrentHorizontalOffsetProperty = DependencyProperty.Register(
"CurrentHorizontalOffset", typeof(double), typeof(ScrollViewer), new PropertyMetadata(ValueBoxes.Double0Box, OnCurrentHorizontalOffsetChanged));
private static void OnCurrentHorizontalOffsetChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
@@ -228,7 +230,7 @@ namespace HandyControl.Controls
/// <summary>
/// 当前水平滚动偏移
/// </summary>
public double CurrentHorizontalOffset
internal double CurrentHorizontalOffset
{
get => (double) GetValue(CurrentHorizontalOffsetProperty);
set => SetValue(CurrentHorizontalOffsetProperty, value);
@@ -15,11 +15,9 @@ namespace HandyControl.Controls
protected override Size MeasureOverride(Size availableSize)
{
var maxSize = new Size();
var children = InternalChildren;
for (int i = 0, count = children.Count; i < count; ++i)
foreach (UIElement child in InternalChildren)
{
var child = children[i];
if (child != null)
{
child.Measure(availableSize);
@@ -0,0 +1,189 @@
using System;
using System.Linq;
using System.Windows;
using HandyControl.Data;
namespace HandyControl.Controls
{
public class SideMenu : HeaderedSimpleItemsControl
{
private SideMenuItem _selectedItem;
private SideMenuItem _selectedHeader;
private bool _isItemSelected;
public SideMenu()
{
AddHandler(SideMenuItem.SelectedEvent, new RoutedEventHandler(SideMenuItemSelected));
Loaded += (s, e) => Init();
}
protected override void Refresh()
{
base.Refresh();
Init();
}
private void Init()
{
if (ItemsHost == null) return;
OnExpandModeChanged(ExpandMode);
}
private void SideMenuItemSelected(object sender, RoutedEventArgs e)
{
if (e.OriginalSource is SideMenuItem item)
{
if (item.Role == SideMenuItemRole.Item)
{
if (Equals(item, _selectedItem)) return;
if (_selectedItem != null)
{
_selectedItem.IsSelected = false;
}
_selectedItem = item;
_selectedItem.IsSelected = true;
RaiseEvent(new FunctionEventArgs<object>(SelectionChangedEvent, this)
{
Info = e.OriginalSource
});
_isItemSelected = true;
}
else
{
if (!Equals(item, _selectedHeader))
{
if (_selectedHeader != null)
{
if (ExpandMode == ExpandMode.Freedom && item.ItemsHost.IsVisible && !_isItemSelected)
{
item.IsSelected = false;
SwitchPanelArea(item);
return;
}
_selectedHeader.IsSelected = false;
if (ExpandMode != ExpandMode.Freedom)
{
SwitchPanelArea(_selectedHeader);
}
}
_selectedHeader = item;
_selectedHeader.IsSelected = true;
SwitchPanelArea(_selectedHeader);
}
else if (ExpandMode == ExpandMode.Freedom && !_isItemSelected)
{
_selectedHeader.IsSelected = false;
SwitchPanelArea(_selectedHeader);
_selectedHeader = null;
}
if (_isItemSelected)
{
_isItemSelected = false;
}
else if(_selectedHeader != null)
{
_selectedHeader.SelectDefaultItem();
_isItemSelected = false;
}
}
}
}
private void SwitchPanelArea(SideMenuItem oldItem)
{
switch (ExpandMode)
{
case ExpandMode.ShowAll:
return;
case ExpandMode.ShowOne:
case ExpandMode.Freedom:
case ExpandMode.Accordion:
oldItem.SwitchPanelArea(oldItem.IsSelected);
break;
}
}
protected override DependencyObject GetContainerForItemOverride() => new SideMenuItem();
protected override bool IsItemItsOwnContainerOverride(object item) => item is SideMenuItem;
public static readonly DependencyProperty ExpandModeProperty = DependencyProperty.Register(
"ExpandMode", typeof(ExpandMode), typeof(SideMenu), new PropertyMetadata(default(ExpandMode), OnExpandModeChanged));
private static void OnExpandModeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var ctl = (SideMenu) d;
var v = (ExpandMode) e.NewValue;
if (ctl.ItemsHost == null)
{
return;
}
ctl.OnExpandModeChanged(v);
}
private void OnExpandModeChanged(ExpandMode mode)
{
if (mode == ExpandMode.ShowAll)
{
ShowAll();
}
else if (mode == ExpandMode.ShowOne)
{
var sideMenuItem = ItemsHost.Children.OfType<SideMenuItem>().FirstOrDefault(item => item.IsSelected);
ShowSelectedOne(sideMenuItem);
}
}
public ExpandMode ExpandMode
{
get => (ExpandMode) GetValue(ExpandModeProperty);
set => SetValue(ExpandModeProperty, value);
}
public static readonly DependencyProperty PanelAreaLengthProperty = DependencyProperty.Register(
"PanelAreaLength", typeof(double), typeof(SideMenu), new PropertyMetadata(double.NaN));
public double PanelAreaLength
{
get => (double) GetValue(PanelAreaLengthProperty);
set => SetValue(PanelAreaLengthProperty, value);
}
private void ShowAll()
{
foreach (var sideMenuItem in ItemsHost.Children.OfType<SideMenuItem>())
{
sideMenuItem.SwitchPanelArea(true);
}
}
private void ShowSelectedOne(SideMenuItem item)
{
foreach (var sideMenuItem in ItemsHost.Children.OfType<SideMenuItem>())
{
sideMenuItem.SwitchPanelArea(Equals(sideMenuItem, item));
}
}
public static readonly RoutedEvent SelectionChangedEvent = EventManager.RegisterRoutedEvent(
"SelectionChanged", RoutingStrategy.Bubble, typeof(EventHandler<FunctionEventArgs<object>>), typeof(SideMenu));
public event EventHandler<FunctionEventArgs<object>> SelectionChanged
{
add => AddHandler(SelectionChangedEvent, value);
remove => RemoveHandler(SelectionChangedEvent, value);
}
}
}
@@ -0,0 +1,152 @@
using System.Linq;
using System.Windows;
using System.Windows.Data;
using System.Windows.Input;
using HandyControl.Data;
using HandyControl.Tools.Extension;
namespace HandyControl.Controls
{
public class SideMenuItem : HeaderedSimpleItemsControl, ISelectable
{
private bool _isMouseLeftButtonDown;
public static readonly DependencyProperty IconProperty = DependencyProperty.Register(
"Icon", typeof(object), typeof(SideMenuItem), new PropertyMetadata(default(object)));
public object Icon
{
get => GetValue(IconProperty);
set => SetValue(IconProperty, value);
}
public SideMenuItem()
{
SetBinding(ExpandModeProperty, new Binding(SideMenu.ExpandModeProperty.Name)
{
RelativeSource = new RelativeSource(RelativeSourceMode.FindAncestor, typeof(SideMenu), 1)
});
}
internal static readonly DependencyProperty ExpandModeProperty =
SideMenu.ExpandModeProperty.AddOwner(typeof(SideMenuItem), new PropertyMetadata(default(ExpandMode)));
internal ExpandMode ExpandMode
{
get => (ExpandMode) GetValue(ExpandModeProperty);
set => SetValue(ExpandModeProperty, value);
}
protected override void Refresh()
{
if (ItemsHost == null) return;
ItemsHost.Children.Clear();
foreach (var item in Items)
{
DependencyObject container;
if (IsItemItsOwnContainerOverride(item))
{
container = item as DependencyObject;
}
else
{
container = GetContainerForItemOverride();
PrepareContainerForItemOverride(container, item);
}
if (container is FrameworkElement element)
{
element.Style = ItemContainerStyle;
ItemsHost.Children.Add(element);
}
}
if (IsLoaded)
{
SwitchPanelArea(ExpandMode == ExpandMode.ShowAll || IsSelected);
}
}
protected virtual void OnSelected(RoutedEventArgs e) => RaiseEvent(e);
public static readonly RoutedEvent SelectedEvent =
EventManager.RegisterRoutedEvent("Selected", RoutingStrategy.Bubble,
typeof(RoutedEventHandler), typeof(SideMenuItem));
public event RoutedEventHandler Selected
{
add => AddHandler(SelectedEvent, value);
remove => RemoveHandler(SelectedEvent, value);
}
public static readonly DependencyProperty IsSelectedProperty = DependencyProperty.Register(
"IsSelected", typeof(bool), typeof(SideMenuItem), new PropertyMetadata(ValueBoxes.FalseBox));
public bool IsSelected
{
get => (bool) GetValue(IsSelectedProperty);
set => SetValue(IsSelectedProperty, value);
}
public static readonly DependencyProperty RoleProperty = DependencyProperty.Register(
"Role", typeof(SideMenuItemRole), typeof(SideMenuItem), new PropertyMetadata(default(SideMenuItemRole)));
public SideMenuItemRole Role
{
get => (SideMenuItemRole) GetValue(RoleProperty);
internal set => SetValue(RoleProperty, value);
}
protected override DependencyObject GetContainerForItemOverride() => new SideMenuItem();
protected override bool IsItemItsOwnContainerOverride(object item) => item is SideMenuItem;
protected override void OnMouseLeave(MouseEventArgs e)
{
base.OnMouseLeave(e);
_isMouseLeftButtonDown = false;
}
protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
{
base.OnMouseLeftButtonDown(e);
_isMouseLeftButtonDown = true;
}
protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e)
{
base.OnMouseLeftButtonUp(e);
if (_isMouseLeftButtonDown)
{
IsSelected = true;
OnSelected(new RoutedEventArgs(SelectedEvent, this));
_isMouseLeftButtonDown = false;
}
}
internal void SelectDefaultItem()
{
if (Role == SideMenuItemRole.Header && ItemsHost.Children.Count > 0)
{
var item = ItemsHost.Children.OfType<SideMenuItem>().FirstOrDefault();
if (item != null && !item.IsSelected)
{
item.OnSelected(new RoutedEventArgs(SelectedEvent, item));
}
}
}
internal void SwitchPanelArea(bool isShow)
{
if (ItemsHost == null) return;
if (Role == SideMenuItemRole.Header)
{
ItemsHost.Show(isShow);
}
}
}
}
@@ -3,6 +3,7 @@ using System.Collections.Specialized;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using HandyControl.Data;
using HandyControl.Tools.Extension;
@@ -10,16 +11,31 @@ namespace HandyControl.Controls
{
[TemplatePart(Name = OverflowButtonKey, Type = typeof(ContextMenuToggleButton))]
[TemplatePart(Name = HeaderPanelKey, Type = typeof(TabPanel))]
[TemplatePart(Name = OverflowScrollviewer, Type = typeof(ScrollViewer))]
[TemplatePart(Name = ScrollButtonLeft, Type = typeof(Button))]
[TemplatePart(Name = ScrollButtonRight, Type = typeof(Button))]
public class TabControl : System.Windows.Controls.TabControl
{
private const string OverflowButtonKey = "PART_OverflowButton";
private const string HeaderPanelKey = "PART_HeaderPanel";
private const string OverflowScrollviewer = "PART_OverflowScrollviewer";
private const string ScrollButtonLeft = "PART_ScrollButtonLeft";
private const string ScrollButtonRight = "PART_ScrollButtonRight";
private ContextMenuToggleButton _buttonOverflow;
private TabPanel _headerPanel;
private ScrollViewer _scrollviewerOverflow;
private Button _buttonScrollLeft;
private Button _buttonScrollRight;
/// <summary>
/// 是否为内部操作
/// </summary>
@@ -115,6 +131,21 @@ namespace HandyControl.Controls
set => SetValue(TabItemHeightProperty, value);
}
/// <summary>
/// 是否可以滚动
/// </summary>
public static readonly DependencyProperty IsScrollableProperty = DependencyProperty.Register(
"IsScrollable", typeof(bool), typeof(TabControl), new PropertyMetadata(ValueBoxes.FalseBox));
/// <summary>
/// 是否可以滚动
/// </summary>
public bool IsScrollable
{
get => (bool) GetValue(IsScrollableProperty);
set => SetValue(IsScrollableProperty, value);
}
/// <summary>
/// 可见的标签数量
/// </summary>
@@ -133,7 +164,7 @@ namespace HandyControl.Controls
if (!IsEnableTabFill)
{
_itemShowCount = (int)(ActualWidth / TabItemWidth);
_buttonOverflow.Show(Items.Count > 0 && Items.Count >= _itemShowCount);
_buttonOverflow.Show(Items.Count > 0 && Items.Count >= _itemShowCount);
}
if (IsInternalAction)
@@ -163,12 +194,33 @@ namespace HandyControl.Controls
public override void OnApplyTemplate()
{
if (_buttonOverflow != null)
{
if (_buttonOverflow.Menu != null)
{
_buttonOverflow.Menu.Closed -= Menu_Closed;
_buttonOverflow.Menu = null;
}
_buttonOverflow.Click -= ButtonOverflow_Click;
}
if (_buttonScrollLeft != null) _buttonScrollLeft.Click -= ButtonScrollLeft_Click;
if (_buttonScrollRight != null) _buttonScrollRight.Click -= ButtonScrollRight_Click;
base.OnApplyTemplate();
_headerPanel = Template.FindName(HeaderPanelKey, this) as TabPanel;
_headerPanel = GetTemplateChild(HeaderPanelKey) as TabPanel;
if (IsEnableTabFill) return;
_buttonOverflow = Template.FindName(OverflowButtonKey, this) as ContextMenuToggleButton;
_buttonOverflow = GetTemplateChild(OverflowButtonKey) as ContextMenuToggleButton;
_scrollviewerOverflow = GetTemplateChild(OverflowScrollviewer) as ScrollViewer;
_buttonScrollLeft = GetTemplateChild(ScrollButtonLeft) as Button;
_buttonScrollRight = GetTemplateChild(ScrollButtonRight) as Button;
if (_buttonScrollLeft != null) _buttonScrollLeft.Click += ButtonScrollLeft_Click;
if (_buttonScrollRight != null) _buttonScrollRight.Click += ButtonScrollRight_Click;
if (_buttonOverflow != null)
{
_itemShowCount = (int)(ActualWidth / TabItemWidth);
@@ -179,49 +231,68 @@ namespace HandyControl.Controls
Placement = PlacementMode.Bottom,
PlacementTarget = _buttonOverflow
};
menu.Closed += (s, e) => _buttonOverflow.IsChecked = false;
menu.Closed += Menu_Closed;
_buttonOverflow.Menu = menu;
_buttonOverflow.Click += (s, e) =>
{
if (_buttonOverflow.IsChecked == true)
{
_buttonOverflow.Menu.Items.Clear();
foreach (TabItem item in Items)
{
var menuItem = new MenuItem
{
Header = item.Header,
Width = TabItemWidth,
IsChecked = item.IsSelected,
IsCheckable = true
};
menuItem.Click += delegate
{
_buttonOverflow.IsChecked = false;
var index = Items.IndexOf(item);
if (index >= _itemShowCount)
{
Items.Remove(item);
Items.Insert(0, item);
if (IsEnableAnimation)
{
_headerPanel.ClearValue(TabPanel.FluidMoveDurationProperty);
}
else
{
_headerPanel.FluidMoveDuration = new Duration(TimeSpan.FromSeconds(0));
}
_headerPanel.ForceUpdate = true;
_headerPanel.Measure(new Size(_headerPanel.DesiredSize.Width, ActualHeight));
_headerPanel.ForceUpdate = false;
}
item.IsSelected = true;
};
_buttonOverflow.Menu.Items.Add(menuItem);
}
}
};
_buttonOverflow.Click += ButtonOverflow_Click;
}
}
private void Menu_Closed(object sender, RoutedEventArgs e) => _buttonOverflow.IsChecked = false;
private void ButtonScrollRight_Click(object sender, RoutedEventArgs e) =>
_scrollviewerOverflow.ScrollToHorizontalOffsetInternal(Math.Min(
_scrollviewerOverflow.CurrentHorizontalOffset + TabItemWidth, _scrollviewerOverflow.ScrollableWidth));
private void ButtonScrollLeft_Click(object sender, RoutedEventArgs e) =>
_scrollviewerOverflow.ScrollToHorizontalOffsetInternal(Math.Max(
_scrollviewerOverflow.CurrentHorizontalOffset - TabItemWidth, 0));
private void ButtonOverflow_Click(object sender, RoutedEventArgs e)
{
if (_buttonOverflow.IsChecked == true)
{
_buttonOverflow.Menu.Items.Clear();
foreach (TabItem item in Items)
{
var menuItem = new MenuItem
{
Header = item.Header,
Width = TabItemWidth,
IsChecked = item.IsSelected,
IsCheckable = true
};
menuItem.Click += delegate
{
_buttonOverflow.IsChecked = false;
var index = Items.IndexOf(item);
if (index >= _itemShowCount)
{
Items.Remove(item);
Items.Insert(0, item);
if (IsEnableAnimation)
{
_headerPanel.ClearValue(TabPanel.FluidMoveDurationProperty);
}
else
{
_headerPanel.FluidMoveDuration = new Duration(TimeSpan.FromSeconds(0));
}
_headerPanel.ForceUpdate = true;
_headerPanel.Measure(new Size(_headerPanel.DesiredSize.Width, ActualHeight));
_headerPanel.ForceUpdate = false;
}
item.IsSelected = true;
};
_buttonOverflow.Menu.Items.Add(menuItem);
}
}
}
internal double GetHorizontalOffset() => _scrollviewerOverflow?.CurrentHorizontalOffset ?? 0;
internal void UpdateScroll() => _scrollviewerOverflow?.RaiseEvent(new MouseWheelEventArgs(Mouse.PrimaryDevice, Environment.TickCount, 0)
{
RoutedEvent = MouseWheelEvent
});
}
}
@@ -87,6 +87,11 @@ namespace HandyControl.Controls
/// </summary>
private int _currentIndex;
/// <summary>
/// 标签容器横向滚动距离
/// </summary>
private double _scrollHorizontalOffset;
/// <summary>
/// 标签容器
/// </summary>
@@ -178,17 +183,21 @@ namespace HandyControl.Controls
base.OnMouseLeftButtonDown(e);
if (TabControlParent.IsDraggable && !ItemIsDragging && !_isDragging)
{
TabControlParent.UpdateScroll();
TabPanel.FluidMoveDuration = new Duration(TimeSpan.FromSeconds(0));
_mouseDownOffsetX = RenderTransform.Value.OffsetX;
var mx = TranslatePoint(new Point(), TabControlParent).X;
_scrollHorizontalOffset = TabControlParent.GetHorizontalOffset();
var mx = TranslatePoint(new Point(), TabControlParent).X + _scrollHorizontalOffset;
_mouseDownIndex = CalLocationIndex(mx);
_maxMoveLeft = -_mouseDownIndex * ItemWidth;
var subIndex = _mouseDownIndex - CalLocationIndex(_scrollHorizontalOffset);
_maxMoveLeft = -subIndex * ItemWidth;
_maxMoveRight = TabControlParent.ActualWidth - ActualWidth + _maxMoveLeft;
_isDragging = true;
ItemIsDragging = true;
_isWaiting = true;
_dragPoint = e.GetPosition(TabControlParent);
_dragPoint = new Point(_dragPoint.X + +_scrollHorizontalOffset, _dragPoint.Y);
_mouseDownPoint = _dragPoint;
CaptureMouse();
}
@@ -199,9 +208,10 @@ namespace HandyControl.Controls
base.OnMouseMove(e);
if (ItemIsDragging && _isDragging)
{
var subX = TranslatePoint(new Point(), TabControlParent).X;
var subX = TranslatePoint(new Point(), TabControlParent).X + _scrollHorizontalOffset;
CurrentIndex = CalLocationIndex(subX);
var p = e.GetPosition(TabControlParent);
p = new Point(p.X + _scrollHorizontalOffset, p.Y);
var subLeft = p.X - _dragPoint.X;
var totalLeft = p.X - _mouseDownPoint.X;
@@ -229,7 +239,7 @@ namespace HandyControl.Controls
ReleaseMouseCapture();
if (_isDragged)
{
var subX = TranslatePoint(new Point(), TabControlParent).X;
var subX = TranslatePoint(new Point(), TabControlParent).X + _scrollHorizontalOffset;
var index = CalLocationIndex(subX);
var left = index * ItemWidth;
var offsetX = RenderTransform.Value.OffsetX;
@@ -273,7 +283,7 @@ namespace HandyControl.Controls
animation.Completed += (s1, e1) => AnimationCompleted();
var f = new TranslateTransform(offsetX, 0);
RenderTransform = f;
f.BeginAnimation(TranslateTransform.XProperty, animation);
f.BeginAnimation(TranslateTransform.XProperty, animation, HandoffBehavior.Compose);
}
/// <summary>
@@ -6,26 +6,23 @@ using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media;
using HandyControl.Data;
using HandyControl.Tools;
namespace HandyControl.Controls
{
[TemplatePart(Name = ElementButtonAm, Type = typeof(RadioButton))]
[TemplatePart(Name = ElementButtonPm, Type = typeof(RadioButton))]
[TemplatePart(Name = ElementButtonConfirm, Type = typeof(Button))]
[TemplatePart(Name = ElementCanvas, Type = typeof(Canvas))]
[TemplatePart(Name = ElementBorderTitle, Type = typeof(Border))]
[TemplatePart(Name = ElementBorderClock, Type = typeof(Border))]
[TemplatePart(Name = ElementPanelNum, Type = typeof(CirclePanel))]
[TemplatePart(Name = ElementTimeStr, Type = typeof(TextBlock))]
public class Clock : Control
public class Clock : ClockBase
{
#region Constants
private const string ElementButtonAm = "PART_ButtonAm";
private const string ElementButtonPm = "PART_ButtonPm";
private const string ElementButtonConfirm = "PART_ButtonConfirm";
private const string ElementCanvas = "PART_Canvas";
private const string ElementBorderTitle = "PART_BorderTitle";
private const string ElementBorderClock = "PART_BorderClock";
@@ -40,8 +37,6 @@ namespace HandyControl.Controls
private RadioButton _buttonPm;
private Button _buttonConfirm;
private Canvas _canvas;
private Border _borderTitle;
@@ -60,59 +55,10 @@ namespace HandyControl.Controls
private int _secValue;
private bool _appliedTemplate;
#endregion Data
#region Public Events
public static readonly RoutedEvent SelectedTimeChangedEvent =
EventManager.RegisterRoutedEvent("SelectedTimeChanged", RoutingStrategy.Direct,
typeof(EventHandler<FunctionEventArgs<DateTime?>>), typeof(Clock));
public event EventHandler<FunctionEventArgs<DateTime?>> SelectedTimeChanged
{
add => AddHandler(SelectedTimeChangedEvent, value);
remove => RemoveHandler(SelectedTimeChangedEvent, value);
}
public event EventHandler<FunctionEventArgs<DateTime>> DisplayTimeChanged;
public event Action Confirmed;
#endregion Public Events
#region Public Properties
public static readonly DependencyProperty SelectedTimeProperty = DependencyProperty.Register(
"SelectedTime", typeof(DateTime?), typeof(Clock), new PropertyMetadata(default(DateTime?), OnSelectedTimeChanged));
private static void OnSelectedTimeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var ctl = (Clock)d;
var v = (DateTime?)e.NewValue;
ctl.DisplayTime = v ?? DateTime.Now;
ctl.OnSelectedTimeChanged(new FunctionEventArgs<DateTime?>(SelectedTimeChangedEvent, ctl)
{
Info = v
});
}
public DateTime? SelectedTime
{
get => (DateTime?) GetValue(SelectedTimeProperty);
set => SetValue(SelectedTimeProperty, value);
}
public static readonly DependencyProperty TimeFormatProperty = DependencyProperty.Register(
"TimeFormat", typeof(string), typeof(Clock), new PropertyMetadata("HH:mm:ss"));
public string TimeFormat
{
get => (string) GetValue(TimeFormatProperty);
set => SetValue(TimeFormatProperty, value);
}
public static readonly DependencyProperty ClockRadioButtonStyleProperty = DependencyProperty.Register(
"ClockRadioButtonStyle", typeof(Style), typeof(Clock), new PropertyMetadata(default(Style)));
@@ -122,32 +68,6 @@ namespace HandyControl.Controls
set => SetValue(ClockRadioButtonStyleProperty, value);
}
public static readonly DependencyProperty DisplayTimeProperty = DependencyProperty.Register(
"DisplayTime", typeof(DateTime), typeof(Clock), new FrameworkPropertyMetadata(DateTime.Now, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnDisplayTimeChanged));
private static void OnDisplayTimeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var ctl = (Clock) d;
var v = (DateTime) e.NewValue;
ctl.Update(v);
ctl.OnDisplayTimeChanged(new FunctionEventArgs<DateTime>(v));
}
public DateTime DisplayTime
{
get => (DateTime) GetValue(DisplayTimeProperty);
set => SetValue(DisplayTimeProperty, value);
}
internal static readonly DependencyProperty ShowConfirmButtonProperty = DependencyProperty.Register(
"ShowConfirmButton", typeof(bool), typeof(Clock), new PropertyMetadata(ValueBoxes.FalseBox));
internal bool ShowConfirmButton
{
get => (bool)GetValue(ShowConfirmButtonProperty);
set => SetValue(ShowConfirmButtonProperty, value);
}
private int SecValue
{
get => _secValue;
@@ -174,7 +94,7 @@ namespace HandyControl.Controls
public override void OnApplyTemplate()
{
_appliedTemplate = false;
AppliedTemplate = false;
if (_buttonAm != null)
{
_buttonAm.Click -= ButtonAm_OnClick;
@@ -185,9 +105,9 @@ namespace HandyControl.Controls
_buttonPm.Click -= ButtonPm_OnClick;
}
if (_buttonConfirm != null)
if (ButtonConfirm != null)
{
_buttonConfirm.Click -= ButtonConfirm_OnClick;
ButtonConfirm.Click -= ButtonConfirm_OnClick;
}
if (_borderTitle != null)
@@ -206,18 +126,18 @@ namespace HandyControl.Controls
_buttonAm = GetTemplateChild(ElementButtonAm) as RadioButton;
_buttonPm = GetTemplateChild(ElementButtonPm) as RadioButton;
_buttonConfirm = GetTemplateChild(ElementButtonConfirm) as Button;
ButtonConfirm = GetTemplateChild(ElementButtonConfirm) as Button;
_borderTitle = GetTemplateChild(ElementBorderTitle) as Border;
_canvas = GetTemplateChild(ElementCanvas) as Canvas;
_borderClock = GetTemplateChild(ElementBorderClock) as Border;
_circlePanel = GetTemplateChild(ElementPanelNum) as CirclePanel;
_blockTime = GetTemplateChild(ElementTimeStr) as TextBlock;
CheckNull();
if (!CheckNull()) return;
_buttonAm.Click += ButtonAm_OnClick;
_buttonPm.Click += ButtonPm_OnClick;
_buttonConfirm.Click += ButtonConfirm_OnClick;
ButtonConfirm.Click += ButtonConfirm_OnClick;
_borderTitle.MouseWheel += BorderTitle_OnMouseWheel;
_canvas.MouseWheel += Canvas_OnMouseWheel;
@@ -241,7 +161,7 @@ namespace HandyControl.Controls
_circlePanel.Children.Add(button);
}
_appliedTemplate = true;
AppliedTemplate = true;
if (SelectedTime.HasValue)
{
Update(SelectedTime.Value);
@@ -255,26 +175,15 @@ namespace HandyControl.Controls
#endregion Public Methods
#region Protected Methods
protected virtual void OnSelectedTimeChanged(FunctionEventArgs<DateTime?> e) => RaiseEvent(e);
protected virtual void OnDisplayTimeChanged(FunctionEventArgs<DateTime> e)
{
var handler = DisplayTimeChanged;
handler?.Invoke(this, e);
}
#endregion Protected Methods
#region Private Methods
private void CheckNull()
private bool CheckNull()
{
if (_buttonPm == null || _buttonAm == null || _buttonConfirm == null || _canvas == null ||
if (_buttonPm == null || _buttonAm == null || ButtonConfirm == null || _canvas == null ||
_borderTitle == null || _borderClock == null || _circlePanel == null ||
_blockTime == null) throw new Exception();
_blockTime == null) return false;
return true;
}
private void BorderTitle_OnMouseWheel(object sender, MouseWheelEventArgs e)
@@ -339,7 +248,7 @@ namespace HandyControl.Controls
private void Update()
{
if (!_appliedTemplate) return;
if (!AppliedTemplate) return;
var hValue = _currentButton.Num;
if (_buttonPm.IsChecked == true)
{
@@ -367,9 +276,9 @@ namespace HandyControl.Controls
/// 更新
/// </summary>
/// <param name="time"></param>
internal void Update(DateTime time)
internal override void Update(DateTime time)
{
if (!_appliedTemplate) return;
if (!AppliedTemplate) return;
var h = time.Hour;
var m = time.Minute;
@@ -396,12 +305,6 @@ namespace HandyControl.Controls
Update();
}
private void ButtonConfirm_OnClick(object sender, RoutedEventArgs e)
{
SelectedTime = DisplayTime;
Confirmed?.Invoke();
}
/// <summary>
/// 获取显示时间
/// </summary>
@@ -0,0 +1,106 @@
using System;
using System.Windows;
using System.Windows.Controls;
using HandyControl.Data;
namespace HandyControl.Controls
{
[TemplatePart(Name = ElementButtonConfirm, Type = typeof(Button))]
public abstract class ClockBase : Control
{
protected const string ElementButtonConfirm = "PART_ButtonConfirm";
protected Button ButtonConfirm;
protected bool AppliedTemplate;
public event Action Confirmed;
public event EventHandler<FunctionEventArgs<DateTime>> DisplayTimeChanged;
public static readonly RoutedEvent SelectedTimeChangedEvent =
EventManager.RegisterRoutedEvent("SelectedTimeChanged", RoutingStrategy.Direct,
typeof(EventHandler<FunctionEventArgs<DateTime?>>), typeof(ClockBase));
public event EventHandler<FunctionEventArgs<DateTime?>> SelectedTimeChanged
{
add => AddHandler(SelectedTimeChangedEvent, value);
remove => RemoveHandler(SelectedTimeChangedEvent, value);
}
public static readonly DependencyProperty TimeFormatProperty = DependencyProperty.Register(
"TimeFormat", typeof(string), typeof(ClockBase), new PropertyMetadata("HH:mm:ss"));
public string TimeFormat
{
get => (string)GetValue(TimeFormatProperty);
set => SetValue(TimeFormatProperty, value);
}
public static readonly DependencyProperty SelectedTimeProperty = DependencyProperty.Register(
"SelectedTime", typeof(DateTime?), typeof(ClockBase), new PropertyMetadata(default(DateTime?), OnSelectedTimeChanged));
private static void OnSelectedTimeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var ctl = (ClockBase)d;
var v = (DateTime?)e.NewValue;
ctl.DisplayTime = v ?? DateTime.Now;
ctl.OnSelectedTimeChanged(new FunctionEventArgs<DateTime?>(SelectedTimeChangedEvent, ctl)
{
Info = v
});
}
public DateTime? SelectedTime
{
get => (DateTime?) GetValue(SelectedTimeProperty);
set => SetValue(SelectedTimeProperty, value);
}
public static readonly DependencyProperty DisplayTimeProperty = DependencyProperty.Register(
"DisplayTime", typeof(DateTime), typeof(ClockBase),
new FrameworkPropertyMetadata(DateTime.Now, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
OnDisplayTimeChanged));
private static void OnDisplayTimeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var ctl = (ClockBase)d;
var v = (DateTime)e.NewValue;
ctl.Update(v);
ctl.OnDisplayTimeChanged(new FunctionEventArgs<DateTime>(v));
}
public DateTime DisplayTime
{
get => (DateTime)GetValue(DisplayTimeProperty);
set => SetValue(DisplayTimeProperty, value);
}
internal static readonly DependencyProperty ShowConfirmButtonProperty = DependencyProperty.Register(
"ShowConfirmButton", typeof(bool), typeof(ClockBase), new PropertyMetadata(ValueBoxes.FalseBox));
internal bool ShowConfirmButton
{
get => (bool) GetValue(ShowConfirmButtonProperty);
set => SetValue(ShowConfirmButtonProperty, value);
}
protected virtual void OnSelectedTimeChanged(FunctionEventArgs<DateTime?> e) => RaiseEvent(e);
protected virtual void OnDisplayTimeChanged(FunctionEventArgs<DateTime> e)
{
var handler = DisplayTimeChanged;
handler?.Invoke(this, e);
}
protected void ButtonConfirm_OnClick(object sender, RoutedEventArgs e)
{
SelectedTime = DisplayTime;
Confirmed?.Invoke();
}
internal abstract void Update(DateTime time);
protected void Clock_SelectedTimeChanged(object sender, FunctionEventArgs<DateTime?> e) => SelectedTime = e.Info;
}
}
@@ -0,0 +1,148 @@
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
namespace HandyControl.Controls
{
[TemplatePart(Name = ElementHourList, Type = typeof(ListBox))]
[TemplatePart(Name = ElementMinuteList, Type = typeof(ListBox))]
[TemplatePart(Name = ElementSecondList, Type = typeof(ListBox))]
public class ListClock : ClockBase
{
#region Constants
private const string ElementHourList = "PART_HourList";
private const string ElementMinuteList = "PART_MinuteList";
private const string ElementSecondList = "PART_SecondList";
#endregion Constants
#region Data
private ListBox _hourList;
private ListBox _minuteList;
private ListBox _secondList;
#endregion Data
public override void OnApplyTemplate()
{
AppliedTemplate = false;
if (ButtonConfirm != null)
{
ButtonConfirm.Click -= ButtonConfirm_OnClick;
}
if (_hourList != null)
{
_hourList.SelectionChanged -= HourList_SelectionChanged;
}
if (_minuteList != null)
{
_minuteList.SelectionChanged -= MinuteList_SelectionChanged;
}
if (_secondList != null)
{
_secondList.SelectionChanged -= SecondList_SelectionChanged;
}
base.OnApplyTemplate();
_hourList = GetTemplateChild(ElementHourList) as ListBox;
if (_hourList != null)
{
CreateItemsSource(_hourList, 24);
_hourList.SelectionChanged += HourList_SelectionChanged;
}
_minuteList = GetTemplateChild(ElementMinuteList) as ListBox;
if (_minuteList != null)
{
CreateItemsSource(_minuteList, 60);
_minuteList.SelectionChanged += MinuteList_SelectionChanged;
}
_secondList = GetTemplateChild(ElementSecondList) as ListBox;
if (_secondList != null)
{
CreateItemsSource(_secondList, 60);
_secondList.SelectionChanged += SecondList_SelectionChanged;
}
ButtonConfirm = GetTemplateChild(ElementButtonConfirm) as Button;
if (ButtonConfirm != null)
{
ButtonConfirm.Click += ButtonConfirm_OnClick;
}
AppliedTemplate = true;
if (SelectedTime.HasValue)
{
Update(SelectedTime.Value);
}
else
{
DisplayTime = DateTime.Now;
Update(DisplayTime);
}
}
private void HourList_SelectionChanged(object sender, SelectionChangedEventArgs e) => Update();
private void MinuteList_SelectionChanged(object sender, SelectionChangedEventArgs e) => Update();
private void SecondList_SelectionChanged(object sender, SelectionChangedEventArgs e) => Update();
private void CreateItemsSource(ItemsControl selector, int count)
{
var list = new List<string>();
for (int i = 0; i < count; i++)
{
list.Add(i.ToString("#00"));
}
selector.ItemsSource = list;
}
private void Update()
{
if (_hourList.SelectedIndex >= 0 && _hourList.SelectedIndex < 24 &&
_minuteList.SelectedIndex >= 0 && _minuteList.SelectedIndex < 60 &&
_secondList.SelectedIndex >= 0 && _secondList.SelectedIndex < 60)
{
var now = DateTime.Now;
DisplayTime = new DateTime(now.Year, now.Month, now.Day, _hourList.SelectedIndex,
_minuteList.SelectedIndex, _secondList.SelectedIndex);
}
}
/// <summary>
/// 更新
/// </summary>
/// <param name="time"></param>
internal override void Update(DateTime time)
{
if (!AppliedTemplate) return;
var h = time.Hour;
var m = time.Minute;
var s = time.Second;
_hourList.SelectedIndex = h;
_minuteList.SelectedIndex = m;
_secondList.SelectedIndex = s;
_hourList.ScrollIntoView(_hourList.SelectedItem);
_minuteList.ScrollIntoView(_minuteList.SelectedItem);
_secondList.ScrollIntoView(_secondList.SelectedItem);
DisplayTime = time;
}
}
}
@@ -30,6 +30,10 @@ namespace HandyControl.Controls
private IEnumerable _itemsSourceInternal;
private IEnumerable _initEnumerable;
private NotifyCollectionChangedEventArgs _initArgs;
public static readonly RoutedEvent SelectionChangedEvent =
EventManager.RegisterRoutedEvent("SelectionChanged", RoutingStrategy.Bubble,
typeof(SelectionChangedEventHandler), typeof(Transfer));
@@ -71,7 +75,22 @@ namespace HandyControl.Controls
_itemsOrigin = GetTemplateChild(ElementItemsOrigin) as SimpleItemsControl;
_itemsSelected = GetTemplateChild(ElementItemsSelected) as SimpleItemsControl;
Refresh();
if (_itemsOrigin != null && _itemsSelected != null)
{
if (_initEnumerable != null)
{
OnItemsSourceChanged(null, _itemsSourceInternal);
_itemsSourceInternal = null;
}
if (_initArgs != null)
{
InternalCollectionChanged(null, _initArgs);
_initArgs = null;
}
Refresh();
}
}
private void AddItem(object item)
@@ -114,6 +133,12 @@ namespace HandyControl.Controls
protected override void OnItemsSourceChanged(IEnumerable oldValue, IEnumerable newValue)
{
if (_itemsOrigin == null || _itemsSelected == null)
{
_initEnumerable = newValue;
return;
}
if (_itemsSourceInternal != null)
{
if (_itemsSourceInternal is INotifyCollectionChanged s)
@@ -139,6 +164,12 @@ namespace HandyControl.Controls
private void InternalCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (_itemsOrigin == null || _itemsSelected == null)
{
_initArgs = e;
return;
}
if (e.OldItems != null)
{
foreach (var item in e.OldItems)
@@ -64,7 +64,7 @@ namespace HandyControl.Controls
public static readonly DependencyProperty NonClientAreaHeightProperty = DependencyProperty.Register(
"NonClientAreaHeight", typeof(double), typeof(Window),
new PropertyMetadata(28.0));
new PropertyMetadata(26.0));
public static readonly DependencyProperty ShowNonClientAreaProperty = DependencyProperty.Register(
"ShowNonClientArea", typeof(bool), typeof(Window),
@@ -288,19 +288,25 @@ namespace HandyControl.Controls
if (WindowState == WindowState.Maximized)
{
BorderThickness = new Thickness();
_tempNonClientAreaHeight = NonClientAreaHeight;
NonClientAreaHeight += 8;
}
else if (WindowState == WindowState.Normal)
{
BorderThickness = _actualBorderThickness;
NonClientAreaHeight = _tempNonClientAreaHeight;
}
}
protected void OnLoaded(RoutedEventArgs args)
{
_actualBorderThickness = BorderThickness;
_tempNonClientAreaHeight = NonClientAreaHeight;
if (WindowState == WindowState.Maximized)
{
BorderThickness = new Thickness();
_tempNonClientAreaHeight += 8;
}
CommandBindings.Add(new CommandBinding(SystemCommands.MinimizeWindowCommand,
@@ -312,7 +318,6 @@ namespace HandyControl.Controls
CommandBindings.Add(new CommandBinding(SystemCommands.CloseWindowCommand, (s, e) => Close()));
CommandBindings.Add(new CommandBinding(SystemCommands.ShowSystemMenuCommand, ShowSystemMenu));
_tempNonClientAreaHeight = NonClientAreaHeight;
_tempWindowState = WindowState;
_tempWindowStyle = WindowStyle;
_tempResizeMode = ResizeMode;
@@ -320,6 +325,11 @@ namespace HandyControl.Controls
SwitchIsFullScreen(_isFullScreen);
SwitchShowNonClientArea(_showNonClientArea);
if (WindowState == WindowState.Maximized)
{
_tempNonClientAreaHeight -= 8;
}
if (SizeToContent != SizeToContent.WidthAndHeight)
return;