CheckComboBox.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. using System;
  2. using System.ComponentModel;
  3. using System.Linq;
  4. using System.Windows;
  5. using System.Windows.Controls;
  6. using System.Windows.Controls.Primitives;
  7. using System.Windows.Data;
  8. using System.Collections.ObjectModel;
  9. using System.Windows.Input;
  10. using SHJX.Service.Library.Common;
  11. namespace CustomUI
  12. {
  13. /// <summary>
  14. /// 多选下拉框
  15. /// </summary>
  16. public class CheckComboBox : Selector
  17. {
  18. #region private fields
  19. private ContentPresenter PART_ContentSite;
  20. private TextBox PART_FilterTextBox;
  21. private ICollectionView view;
  22. private Popup PART_Popup;
  23. private bool mPopupIsFirstOpen;
  24. #endregion
  25. #region DependencyProperty
  26. #region Content
  27. public string Content
  28. {
  29. get { return (string)GetValue(ContentProperty); }
  30. set { SetValue(ContentProperty, value); }
  31. }
  32. public static readonly DependencyProperty ContentProperty =
  33. DependencyProperty.Register("Content", typeof(string), typeof(CheckComboBox), new PropertyMetadata(string.Empty));
  34. #endregion
  35. #region Value
  36. public string Value
  37. {
  38. get { return (string)GetValue(ValueProperty); }
  39. set { SetValue(ValueProperty, value); }
  40. }
  41. public static readonly DependencyProperty ValueProperty =
  42. DependencyProperty.Register("Value", typeof(string), typeof(CheckComboBox), new PropertyMetadata(string.Empty));
  43. #endregion
  44. #region SelectedObjList
  45. public ObservableCollection<object> SelectedObjList
  46. {
  47. get { return (ObservableCollection<object>)GetValue(SelectedObjListProperty); }
  48. set { SetValue(SelectedObjListProperty, value); }
  49. }
  50. public static readonly DependencyProperty SelectedObjListProperty =
  51. DependencyProperty.Register("SelectedObjList", typeof(ObservableCollection<object>), typeof(CheckComboBox), new PropertyMetadata(null));
  52. #endregion
  53. #region SelectedStrList
  54. public ObservableCollection<string> SelectedStrList
  55. {
  56. get { return (ObservableCollection<string>)GetValue(SelectedStrListProperty); }
  57. set { SetValue(SelectedStrListProperty, value); }
  58. }
  59. public static readonly DependencyProperty SelectedStrListProperty =
  60. DependencyProperty.Register("SelectedStrList", typeof(ObservableCollection<string>), typeof(CheckComboBox));
  61. #endregion
  62. #region IsDropDownOpen
  63. public bool IsDropDownOpen
  64. {
  65. get { return (bool)GetValue(IsDropDownOpenProperty); }
  66. set { SetValue(IsDropDownOpenProperty, value); }
  67. }
  68. public static readonly DependencyProperty IsDropDownOpenProperty =
  69. DependencyProperty.Register("IsDropDownOpen", typeof(bool), typeof(CheckComboBox), new PropertyMetadata(false, OnIsDropDownOpenChanged));
  70. private static void OnIsDropDownOpenChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  71. {
  72. CheckComboBox checkComboBox = d as CheckComboBox;
  73. }
  74. #endregion
  75. #region IsShowFilterBox
  76. /// <summary>
  77. /// 获取或者设置下拉列表过滤文本框的显示与隐藏
  78. /// </summary>
  79. public bool IsShowFilterBox
  80. {
  81. get { return (bool)GetValue(IsShowFilterBoxProperty); }
  82. set { SetValue(IsShowFilterBoxProperty, value); }
  83. }
  84. public static readonly DependencyProperty IsShowFilterBoxProperty =
  85. DependencyProperty.Register("IsShowFilterBox", typeof(bool), typeof(CheckComboBox), new PropertyMetadata(false));
  86. #endregion
  87. #region MaxShowNumber
  88. /// <summary>
  89. /// 获取或者设置最多显示的选中个数
  90. /// </summary>
  91. public int MaxShowNumber
  92. {
  93. get { return (int)GetValue(MaxShowNumberProperty); }
  94. set { SetValue(MaxShowNumberProperty, value); }
  95. }
  96. public static readonly DependencyProperty MaxShowNumberProperty =
  97. DependencyProperty.Register("MaxShowNumber", typeof(int), typeof(CheckComboBox), new PropertyMetadata(4));
  98. #endregion
  99. #region MaxDropDownHeight
  100. public double MaxDropDownHeight
  101. {
  102. get { return (double)GetValue(MaxDropDownHeightProperty); }
  103. set { SetValue(MaxDropDownHeightProperty, value); }
  104. }
  105. public static readonly DependencyProperty MaxDropDownHeightProperty =
  106. DependencyProperty.Register("MaxDropDownHeight", typeof(double), typeof(CheckComboBox), new PropertyMetadata(200d));
  107. #endregion
  108. #region FilterBoxWatermark
  109. public string FilterBoxWatermark
  110. {
  111. get { return (string)GetValue(FilterBoxWatermarkProperty); }
  112. set { SetValue(FilterBoxWatermarkProperty, value); }
  113. }
  114. public static readonly DependencyProperty FilterBoxWatermarkProperty =
  115. DependencyProperty.Register("FilterBoxWatermark", typeof(string), typeof(CheckComboBox), new PropertyMetadata("Enter keyword filtering"));
  116. #endregion
  117. #endregion
  118. private bool HasCapture
  119. {
  120. get
  121. {
  122. return Mouse.Captured == this;
  123. }
  124. }
  125. #region Constructors
  126. static CheckComboBox()
  127. {
  128. DefaultStyleKeyProperty.OverrideMetadata(typeof(CheckComboBox), new FrameworkPropertyMetadata(typeof(CheckComboBox)));
  129. }
  130. public CheckComboBox()
  131. {
  132. this.SelectedObjList = new ObservableCollection<object>();
  133. this.SelectedStrList = new ObservableCollection<string>();
  134. }
  135. #endregion
  136. #region Override
  137. public override void OnApplyTemplate()
  138. {
  139. base.OnApplyTemplate();
  140. if (this.PART_FilterTextBox != null)
  141. {
  142. this.PART_FilterTextBox.TextChanged -= PART_FilterTextBox_TextChanged;
  143. }
  144. if (PART_Popup != null)
  145. {
  146. this.PART_Popup.Opened -= PART_Popup_Opened;
  147. }
  148. this.PART_ContentSite = this.GetTemplateChild("PART_ContentSite") as ContentPresenter;
  149. this.PART_FilterTextBox = this.GetTemplateChild("PART_FilterTextBox") as TextBox;
  150. this.PART_Popup = this.GetTemplateChild("PART_Popup") as Popup;
  151. if (this.PART_FilterTextBox != null)
  152. {
  153. this.PART_FilterTextBox.TextChanged += PART_FilterTextBox_TextChanged;
  154. }
  155. view = CollectionViewSource.GetDefaultView(this.ItemsSource);
  156. if (PART_Popup != null)
  157. {
  158. this.PART_Popup.Opened += PART_Popup_Opened;
  159. }
  160. this.Init();
  161. }
  162. protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
  163. {
  164. if (!(item is CheckComboBoxItem))
  165. {
  166. CheckComboBoxItem checkComboBoxItem = element as CheckComboBoxItem;
  167. if (checkComboBoxItem != null && !string.IsNullOrEmpty(this.DisplayMemberPath))
  168. {
  169. Binding binding = new Binding(this.DisplayMemberPath);
  170. checkComboBoxItem.SetBinding(CheckComboBoxItem.ContentProperty, binding);
  171. }
  172. }
  173. base.PrepareContainerForItemOverride(element, item);
  174. }
  175. protected override DependencyObject GetContainerForItemOverride()
  176. {
  177. return new CheckComboBoxItem();
  178. }
  179. protected override bool IsItemItsOwnContainerOverride(object item)
  180. {
  181. return (item is CheckComboBoxItem);
  182. }
  183. #endregion
  184. #region private function
  185. private void Init()
  186. {
  187. this.mPopupIsFirstOpen = true;
  188. if (this.SelectedObjList != null)
  189. {
  190. foreach (var obj in this.SelectedObjList)
  191. {
  192. if (string.IsNullOrWhiteSpace(this.DisplayMemberPath))
  193. {
  194. this.SelectedStrList.Add(obj.ToString());
  195. }
  196. else
  197. {
  198. this.SelectedStrList.Add(CommonUtil.GetPropertyValue(obj, this.DisplayMemberPath).ToString());
  199. }
  200. }
  201. }
  202. this.SetCheckComboBoxValueAndContent();
  203. }
  204. public void SetCheckComboBoxValueAndContent()
  205. {
  206. if (this.SelectedStrList == null) return;
  207. if (this.SelectedStrList.Count > this.MaxShowNumber)
  208. {
  209. this.Content = this.SelectedStrList.Count + " 个被选中";
  210. }
  211. else
  212. {
  213. this.Content = this.SelectedStrList.Aggregate("", (current, p) => current + (p + ", ")).TrimEnd(new char[] { ' ' }).TrimEnd(new char[] { ',' });
  214. }
  215. this.Value = this.SelectedStrList.Aggregate("", (current, p) => current + (p + ",")).TrimEnd(new char[] { ',' });
  216. }
  217. #endregion
  218. #region internal
  219. /// <summary>
  220. /// 行选中
  221. /// </summary>
  222. /// <param name="item"></param>
  223. internal void NotifyCheckComboBoxItemClicked(CheckComboBoxItem item)
  224. {
  225. item.SetValue(CheckComboBoxItem.IsSelectedProperty, !item.IsSelected);
  226. string itemContent = Convert.ToString(item.Content);
  227. if (item.IsSelected)
  228. {
  229. if (!this.SelectedStrList.Contains(item.Content))
  230. {
  231. this.SelectedStrList.Add(itemContent);
  232. }
  233. if (!this.SelectedObjList.Contains(item.DataContext))
  234. {
  235. this.SelectedObjList.Add(item.DataContext);
  236. }
  237. }
  238. else
  239. {
  240. if (this.SelectedStrList.Contains(itemContent))
  241. {
  242. this.SelectedStrList.Remove(itemContent);
  243. }
  244. if (this.SelectedObjList.Contains(item.DataContext))
  245. {
  246. this.SelectedObjList.Remove(item.DataContext);
  247. }
  248. }
  249. this.SetCheckComboBoxValueAndContent();
  250. }
  251. #endregion
  252. #region Event Implement Function
  253. /// <summary>
  254. /// 每次Open回显数据不太好,先这么处理
  255. /// </summary>
  256. /// <param name="sender"></param>
  257. /// <param name="e"></param>
  258. private void PART_Popup_Opened(object sender, EventArgs e)
  259. {
  260. if (!this.mPopupIsFirstOpen) return;
  261. this.mPopupIsFirstOpen = false;
  262. if (this.ItemsSource == null || this.SelectedObjList == null) return;
  263. foreach (var obj in this.SelectedObjList)
  264. {
  265. foreach (var item in this.ItemsSource)
  266. {
  267. if (item == obj)
  268. {
  269. if (ItemContainerGenerator.ContainerFromItem(item) is CheckComboBoxItem checkComboBoxItem)
  270. {
  271. checkComboBoxItem.IsSelected = true;
  272. break;
  273. }
  274. }
  275. }
  276. }
  277. }
  278. private void PART_FilterTextBox_TextChanged(object sender, TextChangedEventArgs e)
  279. {
  280. if (this.PART_FilterTextBox == null || view == null) return;
  281. view.Filter += (o) =>
  282. {
  283. string value = Convert.ToString(CommonUtil.GetPropertyValue(o, this.DisplayMemberPath)).ToLower();
  284. return value.IndexOf(this.PART_FilterTextBox.Text.ToLower()) != -1;
  285. };
  286. }
  287. #endregion
  288. }
  289. }