using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Input; using JD.Filters; using Xceed.Wpf.DataGrid; namespace JD.Pickers.PickerControls { /// /// http://stackoverflow.com/questions/1329362/c-sharp-generics-usercontrol /// The C# compiler does not support Generics inheriting from UserControl, so we need to "hide" the generic in an intermediate class. /// public partial class MultiPicker : UserControl { } /// /// Interaction logic for MultiPicker.xaml /// public class MultiPicker : MultiPicker { private readonly ICollectionView _collectionViewDataList; private readonly ICollectionView _collectionViewSelectionList; // keyboard keys you can use to select/deselect a map private readonly List _selectKeys = new List { Key.Space, Key.Right }; private readonly List _deselectKeys = new List { Key.Space, Key.Delete, Key.Left }; private ObservableCollection DataList { get; } public ObservableCollection Selection { get; } public Filter Filter { get; set; } public MultiPicker(IEnumerable items) { InitializeComponent(); DataList = new ObservableCollection(); Selection = new ObservableCollection(); // populate foreach (var item in items) { DataList.Add(item); } // configure filter Filter = new Filter(typeof(T)) { HasQuickFilter = true, RefreshAction = () => { _collectionViewDataList.Refresh(); } }; _collectionViewDataList = CollectionViewSource.GetDefaultView(DataList); _collectionViewDataList.Filter = Filter.Apply; _collectionViewSelectionList = CollectionViewSource.GetDefaultView(Selection); filterControl.Filter = Filter; // databinding dataGridControl.DataContext = DataList; dataGridControl.ItemsSource = DataList; selectedListControl.ItemsSource = Selection; // link events buttonSelect.Click += SelectEvent; buttonDeselect.Click += DeselectEvent; selectedListControl.KeyUp += DeselectKeyEvent; dataGridControl.KeyUp += SelectKeyEvent; // events for listbox items var style = new Style(typeof(ListBoxItem)); style.Setters.Add(new EventSetter(MouseDoubleClickEvent, new MouseButtonEventHandler(DeselectEvent))); selectedListControl.ItemContainerStyle = style; // events for datarow items style = new Style(typeof(DataRow)); style.Setters.Add(new EventSetter(MouseDoubleClickEvent, new MouseButtonEventHandler(SelectEvent))); dataGridControl.ItemContainerStyle = style; /* disable listbox spacebar selection (so that the spacebar can be used as we want) */ selectedListControl.PreviewKeyDown += (sender, e) => { if (e.Key == Key.Space) { e.Handled = true; } }; dataGridControl.Loaded += SetColumnWidth; } private void SetColumnWidth(object sender, RoutedEventArgs e) { const int minWidth = 150; var totalControlWidth = dataGridControl.ActualWidth; var numberOfColumns = dataGridControl.Columns.Count; foreach (var column in dataGridControl.Columns) { column.Width = Math.Max(totalControlWidth / numberOfColumns, minWidth); } } private void DeselectEvent(object sender, RoutedEventArgs e) { RemoveSelectedViewFromSelection(); } private void DeselectKeyEvent(object sender, KeyEventArgs e) { if (_deselectKeys.Contains(e.Key)) { RemoveSelectedViewFromSelection(); } } private void SelectEvent(object sender, RoutedEventArgs e) { AddSelectedRowsToSelection(); } private void SelectKeyEvent(object sender, KeyEventArgs e) { if (_selectKeys.Contains(e.Key)) { AddSelectedRowsToSelection(); } } private void AddSelectedRowsToSelection() { var selectedItems = dataGridControl.SelectedItems; foreach (T member in selectedItems) { if (!Selection.Contains(member)) { Selection.Add(member); } } dataGridControl.SelectedItems.Clear(); } private void RemoveSelectedViewFromSelection() { while (selectedListControl.SelectedIndex != -1) { var element = selectedListControl.SelectedItem; Selection.Remove((T)element); } _collectionViewSelectionList.Refresh(); } public bool? ShowDialog(Window owner = null) { var dialogWindow = new Window { Content = this, WindowStyle = WindowStyle.ToolWindow, HorizontalContentAlignment = HorizontalAlignment.Stretch, VerticalContentAlignment = VerticalAlignment.Stretch, WindowStartupLocation = WindowStartupLocation.CenterScreen, Width = 750, Owner = owner, Topmost = true }; dialogWindow.Loaded += (sender, e) => filterControl.SearchBox.Focus(); buttonOk.Click += (sender, e) => { dialogWindow.DialogResult = true; }; buttonCancel.Click += (sender, e) => { dialogWindow.DialogResult = false; }; // keyboard shortcuts dialogWindow.KeyUp += (sender, e) => { if (e.Key == Key.Return) { dialogWindow.DialogResult = true; } else if (e.Key == Key.Escape) { dialogWindow.DialogResult = false; } }; return dialogWindow.ShowDialog(); } } }