3. 筛选功能实现【MainWindow.xaml.cs】
本示例为了简化实现,筛选功能处理主要在cs后端实现,如下所示:
1. using System; 2. using System.Collections.Generic; 3. using System.Linq; 4. using System.Text; 5. using System.Threading.Tasks; 6. using System.Windows; 7. using System.Windows.Controls; 8. using System.Windows.Data; 9. using System.Windows.Documents; 10. using System.Windows.Input; 11. using System.Windows.Media; 12. using System.Windows.Media.Imaging; 13. using System.Windows.Navigation; 14. using System.Windows.Shapes; 15. 16. namespace DemoDataGrid 17. { 18. /// <summary> 19. /// Interaction logic for MainWindow.xaml 20. /// </summary> 21. public partial class MainWindow : Window 22. { 23. private MainWindowViewModel viewModel; 24. 25. public MainWindow() 26. { 27. InitializeComponent(); 28. viewModel = new MainWindowViewModel(); 29. this.DataContext = viewModel; 30. } 31. 32. 33. #region 筛选 34. 35. private void TextBlock_MouseRightButtonDown(object sender, MouseButtonEventArgs e) 36. { 37. if (sender != null && sender is TextBlock) 38. { 39. var textBlock = sender as TextBlock; 40. var tag = textBlock.Tag.ToString(); 41. var pop = this.FindName($"popup{tag}"); 42. if (pop != null) 43. { 44. var popup = pop as System.Windows.Controls.Primitives.Popup; 45. if (popup != null) 46. { 47. popup.IsOpen = true; 48. popup.PlacementTarget = textBlock; 49. popup.Placement = System.Windows.Controls.Primitives.PlacementMode.RelativePoint; 50. popup.VerticalOffset = 10; 51. popup.HorizontalOffset = 10; 52. } 53. } 54. } 55. } 56. 57. private void TextBox_TextChanged(object sender, TextChangedEventArgs e) 58. { 59. TextBox textBox = e.OriginalSource as TextBox; 60. var tag = textBox.Tag;//条件 61. var text = textBox.Text; 62. if (tag != null) 63. { 64. if (tag.ToString() == "No") 65. { 66. Filter(this.lbNos.ItemsSource, this.txtNo.Text); 67. } 68. if (tag.ToString() == "Name") 69. { 70. Filter(this.lbNames.ItemsSource, this.txtName.Text); 71. } 72. if (tag.ToString() == "Age") 73. { 74. Filter(this.lbAges.ItemsSource, this.txtAge.Text); 75. } 76. } 77. 78. } 79. 80. private void Filter(object source, string filter) 81. { 82. var cv = CollectionViewSource.GetDefaultView(source); 83. if (cv != null && cv.CanFilter) 84. { 85. cv.Filter = new Predicate<object>((obj) => { 86. bool flag = true; 87. var t = obj as FilterInfo; 88. if (t != null) 89. { 90. flag = t.FilterText.Contains(filter); 91. } 92. return flag; 93. }); 94. } 95. } 96. 97. private void popup_MouseLeave(object sender, MouseEventArgs e) 98. { 99. var popup = e.OriginalSource as System.Windows.Controls.Primitives.Popup; 100. var showContext = (this.FindResource("queryConditionMenu") as ContextMenu)?.IsOpen; 101. if (popup != null && showContext==false) 102. { 103. popup.IsOpen = false; 104. } 105. } 106. 107. private void btnCancel_Click(object sender, RoutedEventArgs e) 108. { 109. var btn = e.OriginalSource as Button; 110. if (btn != null) 111. { 112. var tag = btn.Tag; 113. if (tag.ToString() == "No") 114. { 115. ClearFilter(this.txtNo, this.viewModel.Nos); 116. } 117. if (tag.ToString() == "Name") 118. { 119. ClearFilter(this.txtName, this.viewModel.Names); 120. 121. } 122. if (tag.ToString() == "Age") 123. { 124. ClearFilter(this.txtAge, this.viewModel.Ages); 125. } 126. FilterTask();//清除以后,重新刷新 127. } 128. } 129. 130. private void ClearFilter(TextBox textBox, List<FilterInfo> collection) 131. { 132. textBox.Clear(); 133. foreach (var f in collection) 134. { 135. f.IsChecked = false; 136. } 137. } 138. 139. private void btnOk_Click(object sender, RoutedEventArgs e) 140. { 141. // 142. FilterTask(); 143. } 144. 145. 146. private void FilterTask() 147. { 148. var cv = CollectionViewSource.GetDefaultView(this.dgStudents.ItemsSource); 149. if (cv != null && cv.CanFilter) 150. { 151. cv.Filter = new Predicate<object>((obj) => 152. { 153. bool flag = true; 154. var t = obj as Student; 155. if (t != null) 156. { 157. var nos = this.viewModel.Nos.Where(r => r.IsChecked == true).ToList(); 158. var names = this.viewModel.Names.Where(r => r.IsChecked == true).ToList(); 159. var ages = this.viewModel.Ages.Where(r => r.IsChecked == true).ToList(); 160. if (nos.Count() > 0) 161. { 162. flag = flag && nos.Select(r => r.FilterText).Contains(t.No); 163. } 164. if (names.Count() > 0) 165. { 166. flag = flag && names.Select(r => r.FilterText).Contains(t.Name); 167. } 168. if (ages.Count() > 0) 169. { 170. flag = flag && ages.Select(r => r.FilterText).Contains(t.Age.ToString()); 171. } 172. } 173. return flag; 174. }); 175. } 176. } 177. 178. #endregion 179. 180. private List<string> condition = new List<string>() { "Equal", "NotEqual", "Begin", "End", "In", "NotIn" }; 181. 182. private void ButtonFilter_Click(object sender, RoutedEventArgs e) 183. { 184. var btn = e.OriginalSource as Button; 185. if (btn != null) 186. { 187. var tag = btn.Tag; 188. var popup = this.FindName($"popup{tag}") as System.Windows.Controls.Primitives.Popup; 189. if (popup != null) 190. { 191. popup.IsOpen = true; 192. } 193. if (btn.ContextMenu.IsOpen) 194. { 195. btn.ContextMenu.IsOpen = false; 196. } 197. else 198. { 199. btn.ContextMenu.Tag = tag; 200. btn.ContextMenu.Width = 100; 201. btn.ContextMenu.Height = 150; 202. btn.ContextMenu.IsOpen = true; 203. btn.ContextMenu.PlacementTarget = btn; 204. btn.ContextMenu.Placement = System.Windows.Controls.Primitives.PlacementMode.Bottom; 205. } 206. } 207. } 208. 209. private void ContextMenu_MouseLeave(object sender, MouseEventArgs e) 210. { 211. var menu = e.OriginalSource as ContextMenu; 212. if (menu != null) 213. { 214. menu.IsOpen = false; 215. } 216. } 217. 218. private void ContextMenu_Click(object sender, RoutedEventArgs e) 219. { 220. var contextMenu = sender as ContextMenu; 221. if (contextMenu == null) 222. { 223. return; 224. } 225. var menuItem = e.OriginalSource as MenuItem; 226. if (menuItem == null) 227. { 228. return; 229. } 230. var tag1 = contextMenu.Tag.ToString();//点击的哪一个按钮 231. var tag2 = menuItem.Tag.ToString();//点击的是哪一个菜单 232. var pop = this.FindName($"popup{tag1}Menu"); 233. var comb = this.FindName($"comb{tag1}Menu1"); 234. HideParentPopup(tag1);//隐藏父Popup 235. if (comb != null) 236. { 237. var combMenu = comb as ComboBox; 238. combMenu.SelectedIndex = condition.IndexOf(tag2); 239. } 240. if (pop != null) 241. { 242. var popup = pop as System.Windows.Controls.Primitives.Popup; 243. popup.IsOpen = true; 244. popup.PlacementTarget = dgStudents; 245. popup.Placement = System.Windows.Controls.Primitives.PlacementMode.Center; 246. } 247. } 248. 249. private void btnCancelFilter_Click(object sender, RoutedEventArgs e) 250. { 251. if (sender == null) 252. { 253. return; 254. } 255. var btn = sender as System.Windows.Controls.Button; 256. if (btn != null) 257. { 258. var tag = btn.Tag.ToString(); 259. HidePopupMenu(tag);//隐藏Popup控件 260. if (tag == "No") 261. { 262. ClearMenuFilter(this.txtNoMenu1, this.txtNoMenu2); 263. } 264. if (tag == "Name") 265. { 266. ClearMenuFilter(this.txtNameMenu1, this.txtNameMenu2); 267. } 268. if (tag == "Age") 269. { 270. ClearMenuFilter(this.txtAgeMenu1, this.txtAgeMenu2); 271. } 272. FilterMenuTask(); 273. } 274. } 275. 276. 277. private void btnOkFilter_Click(object sender, RoutedEventArgs e) 278. { 279. if (sender == null) 280. { 281. return; 282. } 283. var btn = sender as System.Windows.Controls.Button; 284. if (btn != null) 285. { 286. var tag = btn.Tag.ToString(); 287. HidePopupMenu(tag); 288. FilterMenuTask(); 289. } 290. } 291. 292. /// <summary> 293. /// 隐藏父Popup 294. /// </summary> 295. /// <param name="tag"></param> 296. private void HideParentPopup(string tag) 297. { 298. //点击右键菜单时,隐藏父Popup控件 299. if (tag == "No") 300. { 301. this.popupNo.IsOpen = false; 302. } 303. if (tag == "Name") 304. { 305. this.popupName.IsOpen = false; 306. } 307. if (tag == "Age") 308. { 309. this.popupAge.IsOpen = false; 310. } 311. } 312. 313. /// <summary> 314. /// 隐藏菜单弹出的Popup控件 315. /// </summary> 316. /// <param name="tag"></param> 317. private void HidePopupMenu(string tag) 318. { 319. var pop = this.FindName($"popup{tag}Menu"); 320. if (pop != null) 321. { 322. var popup = pop as System.Windows.Controls.Primitives.Popup; 323. popup.IsOpen = false; 324. } 325. } 326. 327. /// <summary> 328. /// 清除菜单中的文本过滤条件 329. /// </summary> 330. /// <param name="txt1"></param> 331. /// <param name="txt2"></param> 332. private void ClearMenuFilter(TextBox txt1, TextBox txt2) 333. { 334. txt1?.Clear(); 335. txt2?.Clear(); 336. } 337. 338. /// <summary> 339. /// 340. /// </summary> 341. private void FilterMenuTask() 342. { 343. var cv = CollectionViewSource.GetDefaultView(this.dgStudents.ItemsSource); 344. if (cv != null && cv.CanFilter) 345. { 346. cv.Filter = new Predicate<object>((obj) => 347. { 348. bool flag = true; 349. var t = obj as Student; 350. if (t != null) 351. { 352. string noText1 = this.txtNoMenu1.Text.Trim(); 353. string noText2 = this.txtNoMenu2.Text.Trim(); 354. int noConditionType1 = this.combNoMenu1.SelectedIndex; 355. int noConditionType2 = this.combNoMenu2.SelectedIndex; 356. string nameText1 = this.txtNameMenu1.Text.Trim(); 357. string nameText2 = this.txtNameMenu2.Text.Trim(); 358. int nameConditionType1 = this.combNameMenu1.SelectedIndex; 359. int nameConditionType2 = this.combNameMenu2.SelectedIndex; 360. string ageText1 = this.txtAgeMenu1.Text.Trim(); 361. string ageText2 = this.txtAgeMenu2.Text.Trim(); 362. int ageConditionType1 = this.combAgeMenu1.SelectedIndex; 363. int ageConditionType2 = this.combAgeMenu2.SelectedIndex; 364. bool? isNoAnd = this.rbNoAnd.IsChecked; 365. bool? isNoOr = this.rbNoOr.IsChecked; 366. bool? isNameAnd = this.rbNameAnd.IsChecked; 367. bool? isNameOr = this.rbNameOr.IsChecked; 368. bool? isAgeAnd = this.rbAgeAnd.IsChecked; 369. bool? isAgeOr = this.rbAgeOr.IsChecked; 370. bool flagNo = true; 371. bool flagName = true; 372. bool flagAge = true; 373. flagNo = CheckConditions(noConditionType1, noConditionType2, t.No, noText1, noText2, isNoAnd, isNoOr); 374. flagName = CheckConditions(nameConditionType1, nameConditionType2, t.Name, nameText1, nameText2, isNameAnd, isNameOr); 375. flagAge = CheckConditions(ageConditionType1, ageConditionType2, t.Age.ToString(), ageText1, ageText2, isAgeAnd, isAgeOr); 376. flag = flag && flagNo && flagName && flagAge; 377. } 378. return flag; 379. }); 380. } 381. } 382. 383. private bool CheckConditions(int conditionIndex1, int conditionIndex2, string source, string condition1, string condition2, bool? isAnd, bool? isOr) 384. { 385. bool flag = true; 386. bool flag1 = true; 387. bool flag2 = true; 388. if (!string.IsNullOrEmpty(condition1) && !string.IsNullOrWhiteSpace(condition1) && conditionIndex1 != -1) 389. { 390. flag1 = CheckCondition(conditionIndex1, source, condition1); 391. } 392. if (!string.IsNullOrEmpty(condition2) && !string.IsNullOrWhiteSpace(condition2) && conditionIndex2 != -1) 393. { 394. flag2 = CheckCondition(conditionIndex2, source, condition2); 395. } 396. if (isAnd == true) 397. { 398. flag = flag1 && flag2; 399. } 400. if (isOr == true) 401. { 402. flag = flag1 || flag2; 403. } 404. return flag; 405. } 406. 407. private bool CheckCondition(int condtionIndex, string source, string condition) 408. { 409. bool flag = true; 410. if (condtionIndex == 0) 411. { 412. flag = flag && source == condition; 413. } 414. if (condtionIndex == 1) 415. { 416. flag = flag && source != condition; 417. } 418. if (condtionIndex == 2) 419. { 420. flag = flag && source.StartsWith(condition); 421. } 422. if (condtionIndex == 3) 423. { 424. flag = flag && source.EndsWith(condition); 425. } 426. if (condtionIndex == 4) 427. { 428. flag = flag && source.Contains(condition); 429. } 430. if (condtionIndex == 5) 431. { 432. flag = flag && !source.Contains(condition); 433. } 434. return flag; 435. } 436. } 437. }
学号,姓名,年龄三列过滤列表绑定内容模型一致,为FilterInfo,如下所示:
1. using CommunityToolkit.Mvvm.ComponentModel; 2. using System; 3. using System.Collections.Generic; 4. using System.Linq; 5. using System.Text; 6. using System.Threading.Tasks; 7. 8. namespace DemoDataGrid 9. { 10. public class FilterInfo : ObservableObject 11. { 12. private string filterText; 13. 14. public string FilterText 15. { 16. get { return filterText; } 17. set { SetProperty(ref filterText, value); } 18. } 19. 20. private bool isChecked; 21. 22. public bool IsChecked 23. { 24. get { return isChecked; } 25. set { SetProperty(ref isChecked, value); } 26. } 27. } 28. }
不足与思考
上述筛选实现方式,并非唯一实现,也并非最优实现,同样存在许多可以优化的地方。
在本示例中,存在许多冗余代码,如视图页面,对三列的弹出窗口,内容虽然相对统一,只是列名和绑定内容不同而已,却堆积了三大段代码,是否可以从控件模块或者数据模板的角度,进行简化呢?
筛选功能实现上,同样存在许多冗余代码,是否可以进行简化呢?以上是我们需要思考的地方,希望可以集思广益,共同学习,一起进步。