using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows.Controls; using HeuristicLab.MainForm.WPF; using System.Windows; using System.Collections.ObjectModel; using System.Collections.Specialized; using System.Windows.Controls.Primitives; using System.Collections; using System.Diagnostics; using System.ComponentModel; namespace HeuristicLab.OKB.Cockpit.Admin { public partial class ItemSelector : UserControl, IOKBCockpitItem { class SelectionWrapper { public event EventHandler IsCheckedChanged; private bool isChecked; public bool IsChecked { get { return isChecked; } set { if (value == isChecked) return; isChecked = value; OnIsCheckedChanged(); } } public object Obj { get; set; } public SelectionWrapper() { } public SelectionWrapper(object o) { Obj = o; } protected void OnIsCheckedChanged() { if (IsCheckedChanged != null) IsCheckedChanged(this, new EventArgs()); } public override bool Equals(object obj) { return Obj.Equals(obj); } public override int GetHashCode() { if (Obj == null) return 0; return Obj.GetHashCode(); } } public static DependencyProperty AvailableObjectsProperty = DependencyProperty.Register( "AvailableObjects", typeof(ObservableCollection), typeof(ItemSelector), new PropertyMetadata(new ObservableCollection())); public static DependencyProperty SelectedObjectsProperty = DependencyProperty.Register( "SelectedObjects", typeof(ObservableCollection), typeof(ItemSelector), new PropertyMetadata(new ObservableCollection())); public ObservableCollection AvailableObjects { get { return (ObservableCollection)GetValue(AvailableObjectsProperty); } set { SetValue(AvailableObjectsProperty, value); } } public ObservableCollection SelectedObjects { get { return (ObservableCollection)GetValue(SelectedObjectsProperty); } set { SetValue(SelectedObjectsProperty, value); } } private ObservableCollection DisplayedAvailableObjects; protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e) { base.OnPropertyChanged(e); if (e.Property == AvailableObjectsProperty) { ((ObservableCollection)e.OldValue).CollectionChanged -= PropageAvailableObjectsChange; AvailableObjects.CollectionChanged += PropageAvailableObjectsChange; PropageAvailableObjectsChange(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); ValidateSelection(); } else if (e.Property == SelectedObjectsProperty) { ValidateSelection(); } } private void ValidateSelection() { if (SelectedObjects == null) return; var selectedObjects = new HashSet(SelectedObjects); SelectedObjects.Clear(); if (AvailableObjects != null) { selectedObjects.IntersectWith(AvailableObjects); foreach (var wrapper in DisplayedAvailableObjects) wrapper.IsChecked = selectedObjects.Contains(wrapper.Obj); foreach (var o in selectedObjects) SelectedObjects.Add(o); } } private void PropageAvailableObjectsChange(object sender, NotifyCollectionChangedEventArgs args) { switch (args.Action) { case NotifyCollectionChangedAction.Add: foreach (var o in args.NewItems) DisplayedAvailableObjects.Add(new SelectionWrapper(o)); break; case NotifyCollectionChangedAction.Move: DisplayedAvailableObjects.Move(args.OldStartingIndex, args.NewStartingIndex); break; case NotifyCollectionChangedAction.Remove: foreach (var o in args.OldItems) DisplayedAvailableObjects.Remove(new SelectionWrapper(o)); break; case NotifyCollectionChangedAction.Replace: foreach (var o in args.OldItems) DisplayedAvailableObjects.Remove(new SelectionWrapper(o)); foreach (var o in args.NewItems) DisplayedAvailableObjects.Insert(args.OldStartingIndex, new SelectionWrapper(o)); break; case NotifyCollectionChangedAction.Reset: DisplayedAvailableObjects.Clear(); foreach (var o in AvailableObjects) DisplayedAvailableObjects.Add(new SelectionWrapper(o)); break; } } public ItemSelector() { InitializeComponent(); DisplayedAvailableObjects = new ObservableCollection(); AvailableObjectsList.ItemsSource = DisplayedAvailableObjects; SelectedObjectsList.DataContext = this; SelectedObjectsList.SetBinding(ListBox.ItemsSourceProperty, "SelectedObjects"); AvailableObjects.CollectionChanged += PropageAvailableObjectsChange; } protected void OnAvailableClicked(object sender, RoutedEventArgs args) { ToggleButton button = args.OriginalSource as ToggleButton; if (button == null) return; SelectionWrapper wrapper = button.Tag as SelectionWrapper; if (wrapper == null) return; if (!SelectedObjects.Contains(wrapper.Obj)) { SelectedObjects.Add(wrapper.Obj); wrapper.IsChecked = true; } else { SelectedObjects.Remove(wrapper.Obj); wrapper.IsChecked = false; } } protected void OnSelectedClicked(object sender, RoutedEventArgs args) { Button button = args.OriginalSource as Button; if (button == null) return; object o = button.Tag; Debug.Assert(SelectedObjects.Contains(o)); SelectedObjects.Remove(o); var wrappers = DisplayedAvailableObjects.Where(w => w.Obj == o); foreach (var w in wrappers) w.IsChecked = false; } } }