202 lines
6.4 KiB
C#
202 lines
6.4 KiB
C#
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
|
|
{
|
|
/// <summary>
|
|
/// 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.
|
|
/// </summary>
|
|
public partial class MultiPicker : UserControl
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// Interaction logic for MultiPicker.xaml
|
|
/// </summary>
|
|
public class MultiPicker<T> : MultiPicker
|
|
{
|
|
private readonly ICollectionView _collectionViewDataList;
|
|
private readonly ICollectionView _collectionViewSelectionList;
|
|
|
|
// keyboard keys you can use to select/deselect a map
|
|
private readonly List<Key> _selectKeys = new List<Key> { Key.Space, Key.Right };
|
|
private readonly List<Key> _deselectKeys = new List<Key> { Key.Space, Key.Delete, Key.Left };
|
|
|
|
private ObservableCollection<T> DataList { get; }
|
|
|
|
public ObservableCollection<T> Selection { get; }
|
|
|
|
public Filter Filter { get; set; }
|
|
|
|
public MultiPicker(IEnumerable<T> items)
|
|
{
|
|
InitializeComponent();
|
|
|
|
DataList = new ObservableCollection<T>();
|
|
Selection = new ObservableCollection<T>();
|
|
|
|
// 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();
|
|
}
|
|
}
|
|
}
|