SegmentControl.cs 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. using System.Windows;
  2. using System.ComponentModel;
  3. using System.Windows.Controls;
  4. using System.Collections.Specialized;
  5. namespace CustomUI
  6. {
  7. /// <summary>
  8. /// 分段按钮控件,类似IOS的SegmentControl
  9. /// </summary>
  10. /// <remarks>add by zhidf 2017.7.9</remarks>
  11. public class SegmentControl : ListBox
  12. {
  13. #region private fields
  14. #endregion
  15. #region DependencyProperty
  16. #region CornerRadius
  17. /// <summary>
  18. /// 获取或者设置空间的边框圆角
  19. /// </summary>
  20. [Bindable(true), Description("获取或者设置空间的边框圆角")]
  21. public CornerRadius CornerRadius
  22. {
  23. get { return (CornerRadius)GetValue(CornerRadiusProperty); }
  24. set { SetValue(CornerRadiusProperty, value); }
  25. }
  26. public static readonly DependencyProperty CornerRadiusProperty =
  27. DependencyProperty.Register("CornerRadius", typeof(CornerRadius), typeof(SegmentControl));
  28. #endregion
  29. #region IsAllRound
  30. /// <summary>
  31. /// 获取或者设置SegmentItem的四周的圆角是否与SegmentControl一致
  32. /// </summary>
  33. [Bindable(true), Description("获取或者设置SegmentItem的四周的圆角是否与SegmentControl一致")]
  34. public bool IsAllRound
  35. {
  36. get { return (bool)GetValue(IsAllRoundProperty); }
  37. set { SetValue(IsAllRoundProperty, value); }
  38. }
  39. public static readonly DependencyProperty IsAllRoundProperty =
  40. DependencyProperty.Register("IsAllRound", typeof(bool), typeof(SegmentControl), new PropertyMetadata(false));
  41. #endregion
  42. #endregion
  43. #region 路由事件
  44. #region ItemClickEvent
  45. public static readonly RoutedEvent ItemClickEvent = EventManager.RegisterRoutedEvent("ItemClick",
  46. RoutingStrategy.Bubble, typeof(RoutedPropertyChangedEventHandler<object>), typeof(SegmentControl));
  47. public event RoutedPropertyChangedEventHandler<object> ItemClick
  48. {
  49. add
  50. {
  51. this.AddHandler(ItemClickEvent, value);
  52. }
  53. remove
  54. {
  55. this.RemoveHandler(ItemClickEvent, value);
  56. }
  57. }
  58. public virtual void OnItemClick(object oldValue, object newValue)
  59. {
  60. RoutedPropertyChangedEventArgs<object> arg = new RoutedPropertyChangedEventArgs<object>(oldValue, newValue, ItemClickEvent);
  61. this.RaiseEvent(arg);
  62. }
  63. #endregion
  64. #endregion
  65. #region Constructors
  66. static SegmentControl()
  67. {
  68. DefaultStyleKeyProperty.OverrideMetadata(typeof(SegmentControl), new FrameworkPropertyMetadata(typeof(SegmentControl)));
  69. }
  70. #endregion
  71. #region Override
  72. protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
  73. {
  74. int index = this.ItemContainerGenerator.IndexFromContainer(element);
  75. SegmentItem segmentItem = element as SegmentItem;
  76. if (segmentItem == null)
  77. {
  78. return;
  79. }
  80. if (index == 0)
  81. {
  82. segmentItem.IsFirstItem = true;
  83. segmentItem.CornerRadius = new CornerRadius(this.CornerRadius.TopLeft, 0, 0, this.CornerRadius.BottomLeft);
  84. }
  85. if (index == this.Items.Count - 1)
  86. {
  87. segmentItem.IsLastItem = true;
  88. segmentItem.CornerRadius = new CornerRadius(0, this.CornerRadius.TopRight, this.CornerRadius.BottomRight, 0);
  89. }
  90. if(this.IsAllRound)
  91. {
  92. segmentItem.CornerRadius = this.CornerRadius;
  93. segmentItem.BorderThickness = new Thickness(0);
  94. segmentItem.Padding = new Thickness(20, 5, 20, 5);
  95. }
  96. base.PrepareContainerForItemOverride(segmentItem, item);
  97. }
  98. protected override DependencyObject GetContainerForItemOverride()
  99. {
  100. return new SegmentItem();
  101. }
  102. public override void OnApplyTemplate()
  103. {
  104. base.OnApplyTemplate();
  105. }
  106. protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e)
  107. {
  108. base.OnItemsChanged(e);
  109. //以下代码是为了新增项或者移除项时,正确设置每个Item的外观
  110. switch (e.Action)
  111. {
  112. case NotifyCollectionChangedAction.Add:
  113. if (e.NewStartingIndex == 0) //如果新添加项是放在第一位,则更改原来的第一位的属性值
  114. {
  115. this.SetSegmentItem(e.NewStartingIndex + e.NewItems.Count);
  116. }
  117. //如果新添加项是放在最后一位,则更改原来的最后一位的属性值
  118. if (e.NewStartingIndex == this.Items.Count - e.NewItems.Count)
  119. {
  120. this.SetSegmentItem(e.NewStartingIndex - 1);
  121. }
  122. break;
  123. case NotifyCollectionChangedAction.Remove:
  124. if (e.OldStartingIndex == 0) //如果移除的是第一个,则更改更新后的第一项的属性值
  125. {
  126. this.SetSegmentItem(0);
  127. }
  128. else
  129. {
  130. this.SetSegmentItem(e.OldStartingIndex - 1);
  131. }
  132. break;
  133. }
  134. }
  135. #endregion
  136. #region private function
  137. /// <summary>
  138. /// 设置SegmentItem的位置属性
  139. /// </summary>
  140. /// <param name="index"></param>
  141. private void SetSegmentItem(int index)
  142. {
  143. if (index > this.Items.Count || index < 0)
  144. {
  145. return;
  146. }
  147. SegmentItem segmentItem = this.ItemContainerGenerator.ContainerFromIndex(index) as SegmentItem;
  148. if (segmentItem == null)
  149. {
  150. return;
  151. }
  152. segmentItem.IsFirstItem = index == 0;
  153. segmentItem.IsLastItem = index == this.Items.Count - 1;
  154. segmentItem.IsMiddleItem = index > 0 && index < this.Items.Count - 1;
  155. }
  156. #endregion
  157. #region Event Implement Function
  158. #endregion
  159. }
  160. }