Другой пример, если вам нужно узнать, какие элементы были выбраны в ListBox, используйте клавишу SHIFT для создания расширенного выделения, даже если вам не нужно инициировать операцию Draq&Drop
:
Используя образец данных, который вы предоставили в вопросе, a List<ListItemsTest>
.
В этом примере List<int>
(lbSelectedIndexes
) используется для отслеживания того, какие элементы в настоящий момент выбраны в ListBox.Этот список заполняется только тогда, когда выбор выполняется с помощью клавиши SHIFT
или после запуска операции перетаскивания.Это может быть полезно для определения типа выбора.
Во всех остальных случаях List<int>
пуст, а коллекции SelectedItems
и SelectedIndices
могут использоваться для определения элементов, выбранных в данный момент.
Значение SystemInformation.DragSize
также используется для определения необходимости запуска операции перетаскивания при перемещении указателя мыши при нажатой левой кнопке.
При запуске операции перетаскивания новый DataObject заполняется элементами ListBox, соответствующими текущему выбору, независимо от того, как был выполнен выбор.
DragDropEffects устанавливается вDragDropEffects.Copy
.
Point lbMouseDownPosition = Point.Empty;
List<int> lbSelectedIndexes = new List<int>();
private void listBox1_MouseDown(object sender, MouseEventArgs e)
{
var lb = sender as ListBox;
lbMouseDownPosition = e.Location;
lbSelectedIndexes = new List<int>();
int idx = lb.IndexFromPoint(e.Location);
if (ModifierKeys == Keys.Shift && idx != lb.SelectedIndex) {
lbSelectedIndexes.AddRange(Enumerable.Range(
Math.Min(idx, lb.SelectedIndex),
Math.Abs((idx - lb.SelectedIndex)) + 1).ToArray());
}
}
private void listBox1_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left &&
((Math.Abs(e.X - lbMouseDownPosition.X) > SystemInformation.DragSize.Width) ||
(Math.Abs(e.Y - lbMouseDownPosition.Y) > SystemInformation.DragSize.Height)))
{
var lb = sender as ListBox;
DataObject obj = new DataObject();
if (lbSelectedIndexes.Count == 0) {
lbSelectedIndexes = lb.SelectedIndices.OfType<int>().ToList();
}
List<object> selection = lb.Items.OfType<object>().Where((item, idx) =>
lbSelectedIndexes.IndexOf(idx) >= 0).ToList();
obj.SetData(typeof(IList<ListItemsTest>), selection);
lb.DoDragDrop(obj, DragDropEffects.Copy);
}
}
Чтобы проверить результаты, перетащите другой ListBox (listBox2
, здесь) в форму,установите для его свойства AlloDrop
значение true
и подпишитесь на события DragEnter
и DragDrop
.
Когда указатель мыши входит во вторую клиентскую область ListBox, эффект DragDropEffects.Copy
срабатывает, если метод e.Data.GetDataPresent () обнаруживает, что перетаскиваемый объект содержит List<ListItemsTest>
.
Если формат данных принят, объект данных преобразуется обратно в List<ListItemsTest>
- с использованием метода IDataObject.GetData () - и устанавливается какDataSource
из listBox2
.
private void listBox2_DragDrop(object sender, DragEventArgs e)
{
ListBox lb = sender as ListBox;
if (e.Data != null && e.Data.GetDataPresent(typeof(IList<ListItemsTest>))) {
lb.DisplayMember = "Name";
lb.ValueMember = "ID";
lb.DataSource = e.Data.GetData(typeof(IList<ListItemsTest>));
}
}
private void listBox2_DragEnter(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(typeof(IList<ListItemsTest>))) {
e.Effect = DragDropEffects.Copy;
}
}