מבנה נתונים גלובלי עבור Checked TreeView ב-Wpf
-
כידוע, הדרך הטובה ביותר להתנהל עם TreeView ב-WPF היא עם מבנה נתונים הררכי, ו-HierarchicalDataTemplate ב-WPF נבנה במיוחד למטרה זו.
אחרי שמצאתי את עצמי בפעם השלישית בונה מבנה נתונים עבור Checked TreeView (ראה תמונה), החלטתי לשבת כמה דקות ולבנות משהו יותר גלובלי שיאפשר לי להשתמש בו גם בעתיד. הרעיון הוא לייצר מחלקה בסיסית המכילה את כל מה שדרוש עבור מטרה זו, כך שאוכל לרשת אותה ולהשתמש בה עבור כל מבנה נתונים הררכי באופן כללי עם הדרישה הזו של Checked TreeView.שימו לב! אני הגדרתי את ה-Default של ה-IsChecked כ-false ייתכן ותרצו לשנות את זה ל-true תלוי באמפלמנטציה שלכם.
אם לא הבנתם את הנושא דיו והוא מעניין אתכם? אנא קיראו כתבה זו כהקדמה:
https://www.codeproject.com/Articles/26288/Simplifying-the-WPF-TreeView-by-Using-the-ViewModeלהלן הקוד:
using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; namespace MyModels { public class CheckedTreeViewItemModelBase : ViewModelBase { string _name; bool? _isChecked = false; ObservableCollection<CheckedTreeViewItemModelBase> _children = new ObservableCollection<CheckedTreeViewItemModelBase>(); public CheckedTreeViewItemModelBase Parent; public virtual string Name { get => _name; set => SetProperty(ref _name, value); } public bool? IsChecked { get => _isChecked; set => SetCheckedValue(value, true); } public ObservableCollection<CheckedTreeViewItemModelBase> Children { get => _children; set => SetChildren(value); } public override string ToString() => Name; void SetChildren(ObservableCollection<CheckedTreeViewItemModelBase> children) { if (SetProperty(ref _children, children)) { foreach (var child in _children) child.Parent = this; } } public void SetCheckedValue(bool? isChecked, bool updateChildren) { if (SetProperty(ref _isChecked, isChecked, nameof(IsChecked))) { if (updateChildren && Children != null) { foreach (var child in Children) { if (child.IsChecked != isChecked) child.IsChecked = (isChecked == true); } } if (Parent != null) { var parentCheckedValue = Parent.Children.All(c => c.IsChecked == true) ? true : Parent.Children.All(c => c.IsChecked == false) ? (bool?)false : null; Parent.SetCheckedValue(parentCheckedValue, false); } } } public IEnumerable<CheckedTreeViewItemModelBase> GetAllCheckedChildren() { if (Children != null) { foreach (var child in Children) { if (child.IsChecked == true) yield return child; foreach (var item in child.GetAllCheckedChildren()) yield return item; } } } } }
המודל יורש מודל אחר שימושי בשם ViewModelBase המהווה בסיס טוב עבור כל viewModle ב-Wpf
using System.Collections.Generic; using System.ComponentModel; using System.Runtime.CompilerServices; namespace MyModels { public class ViewModelBase : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } protected bool SetProperty<T>(ref T field, T value, [CallerMemberName] string propertyName = null) { if (EqualityComparer<T>.Default.Equals(field, value)) return false; field = value; OnPropertyChanged(propertyName); return true; } } }