Какие элементы WinForms выбрать для to do list?

Хочу написать на C# десктопную программку. В данном проекте задачи в списке должны иметь приоритеты (срочно-не срочно, важно-не важно) и отображаться в отдельных блоках (их будет 4 на главном окне) и задачу из одного блока можно переместить в другой. Подскажите, пожалуйста, какие мне использовать для реализации проекта элементы в WinForms? TextBox не подойдут из-за волшебной функции перемещения задач между блоками. Ограничена во времени, из-за этого гуглить нет возможности.


Ответы (1 шт):

Автор решения: rotabor

В качестве источника подойдёт любой элемент - события мышки поддерживают все. В качестве приёмника подойдут все элементы, унаследованные от Control (а это практически все) - они должны иметь свойство AllowDrop. TextBox походит под обе категории.

Вот работающий пример по материалу из Сохабра:

namespace WinFormsApp1;
public partial class Form1 : Form {
    private System.ComponentModel.IContainer components = null;
    ListView DragSrc; ListBox DragTgt;
    int idxDragItm, idxDropItm;
    Rectangle dragBox;
    protected override void Dispose(bool disposing) {
        if (disposing && (components != null)) { components.Dispose(); }
        base.Dispose(disposing);
    }
    public Form1() {
        SuspendLayout();
        DragSrc = new ListView() {
            Location = new Point(73, 54), Name = "DragSrc"
            , Size = new Size(206, 130), TabIndex = 3
            , UseCompatibleStateImageBehavior = false, View = View.Details
        };
        DragSrc.Columns.AddRange(new ColumnHeader[] {
            new ColumnHeader() { Text = "Имя", Width = 100 }
            , new ColumnHeader() { Text = "Фамилия", Width = 100 } });
        DragSrc.MouseDown += DragSrc_MouseDown;
        DragSrc.MouseMove += DragSrc_MouseMove;
        DragSrc.MouseUp += DragSrc_MouseUp;
        DragTgt = new ListBox() {
            AllowDrop = true, FormattingEnabled = true, ItemHeight = 15
            , Location = new Point(384, 54), Name = "DragTgt"
            , Size = new Size(146, 124), TabIndex = 4
        };
        DragTgt.DragDrop += DragTgt_DragDrop;
        DragTgt.DragOver += DragTgt_DragOver;
        AutoScaleDimensions = new SizeF(7F, 15F);
        AutoScaleMode = AutoScaleMode.Font; ClientSize = new Size(800, 450);
        Controls.AddRange(new Control[] { DragTgt, DragSrc });
        Name = Text = "Form1";
        ResumeLayout(false);
    }
    protected override void OnLoad(EventArgs e) {
        DragSrc.Items.AddRange(
            new ListViewItem[] { new ListViewItem(new string[]{ "Иван", "Петров" })
            , new ListViewItem(new string[]{ "Алексей", "Сидоров" })
            , new ListViewItem(new string[]{ "Дормидонт", "Семинарский" })});
    }
    private void DragSrc_MouseDown(object sender, MouseEventArgs e) {
        idxDragItm = DragSrc.Items.IndexOf(DragSrc.GetItemAt(e.X, e.Y));
        if (idxDragItm != ListBox.NoMatches) {
            Size dragSize = SystemInformation.DragSize;
            dragBox = new Rectangle(
                new Point(e.X - (dragSize.Width / 2), e.Y - (dragSize.Height / 2))
                , dragSize);
        }
        else dragBox = Rectangle.Empty;
    }
    private void DragSrc_MouseUp(object sender, MouseEventArgs e) {
        dragBox = Rectangle.Empty;
    }
    private void DragSrc_MouseMove(object sender, MouseEventArgs e) {
        if ((e.Button & MouseButtons.Left) == MouseButtons.Left) {
            if (dragBox != Rectangle.Empty && !dragBox.Contains(e.X, e.Y)) {
                DragDropEffects dropEffect = DragSrc.DoDragDrop(
                    DragSrc.Items[idxDragItm], DragDropEffects.All);
                if (dropEffect == DragDropEffects.Move) {
                    DragSrc.Items.RemoveAt(idxDragItm);
                    if (idxDragItm > 0)
                        DragSrc.Items[idxDragItm - 1].Selected = true;
                    else if (DragSrc.Items.Count > 0)
                        DragSrc.Items[0].Selected = true;
                }
            }
        }
    }
    private void DragTgt_DragOver(object sender, DragEventArgs e) {
        if ((e.KeyState & 8) == 8 && (e.AllowedEffect & DragDropEffects.Copy)
                == DragDropEffects.Copy)
            e.Effect = DragDropEffects.Copy;
        else if ((e.AllowedEffect & DragDropEffects.Move) == DragDropEffects.Move)
            e.Effect = DragDropEffects.Move;
        else e.Effect = DragDropEffects.None;
        idxDropItm = DragTgt.IndexFromPoint(
            DragTgt.PointToClient(new Point(e.X, e.Y)));
    }
    private void DragTgt_DragDrop(object sender, DragEventArgs e) {
        var item = e.Data.GetData(typeof(ListViewItem));
        if (e.Effect == DragDropEffects.Copy || e.Effect == DragDropEffects.Move) {
            if (idxDropItm != ListBox.NoMatches)
                DragTgt.Items.Insert(idxDropItm, ((ListViewItem)item).ToString());
            else
                DragTgt.Items.Add(((ListViewItem)item).ToString());
        }
    }
}
internal static class Program {
    [STAThread]
    static void Main() {
        ApplicationConfiguration.Initialize();
        Application.Run(new Form1());
    }
}

Создаёте новый проект WinForms, удаляете там Form1, а этим кодом заменяете код в Program.

На что здесь нужно обратить внимание (зависит от элементов):

  1. Захват элемента в источнике - нужно идентифицировать указываемый элемент DragSrc_MouseDown --> "idxDragItm = DragSrc.Items.IndexOf(DragSrc.GetItemAt(e.X, e.Y))".
  2. Отпускание элемента в приёмнике - нужно преобразовать из одного типа в другой DragTgt_DragDrop --> "DragTgt.Items.Insert(idxDropItm, ((ListViewItem)item).ToString())".

Всё остальное изменений не требует.

→ Ссылка