【问题标题】:MultiExtended ListBox selection issue多扩展列表框选择问题
【发布时间】:2026-02-17 02:40:01
【问题描述】:

我正在尝试使用 C# 中的多扩展 ListBox 用户控件执行以下操作。

假设我有一个项目列表框

item 1 
item 2 
item 3 
item 4 
item 5 

然后我选择第 1 项和第 2 项。

如果我按下 Ctrl + Down 键,列表框变为

item 3 
item 1
item 2 
item 4 
item 5 

现在,我的算法运行良好,但我无法保留所选项目的列表。 在我按下 Ctrl + Down/Up 键后,所有选定的项目都被移动,但只有一个项目 最后被选中。

我想在按键后保留所选项目的列表。

我认为这是因为 MultiExtended ListBoxDown/Up 键的默认功能。

除了使用多重简单列表框和添加更多功能之外,还有其他方法可以解决此问题吗?

【问题讨论】:

    标签: c# winforms listbox


    【解决方案1】:

    我使用自己的本地代码重新创建了您的问题,但遇到了与您相同的问题。

    我发现我的问题在于尝试在 KeyDown 事件期间更改数据顺序。

    我设法通过在 KeyDown 事件完成后处理订单更改来使其工作。

    不过,我仍然需要恢复 ListBox 的选择。

    这是我的代码:

    public partial class mainForm : Form {
    
        delegate void noParamsDelegate();
        Stack<noParamsDelegate> methodsToCallWhenIdle = new Stack<noParamsDelegate>();
    
        void application_Idle( object sender, EventArgs e ) {
            if( methodsToCallWhenIdle.Count > 0 ) {
                methodsToCallWhenIdle.Pop()(); // Call the deligate at the top of the stack
            }
        }
    
        public mainForm() {
            InitializeComponent();
    
            Application.Idle += new EventHandler( application_Idle );
            bindExampleDataToListBox();
            listBox.KeyDown += new KeyEventHandler( listBox_KeyDown );
        }
    
        ListItems boundList = new ListItems();
    
        void listBox_KeyDown( object sender, KeyEventArgs e ) {
            if( e.Control && methodsToCallWhenIdle.Count == 0 ) {
                if( e.KeyCode == Keys.Down ) {
                copyOfSelectedItems = createCopyOfSelectedItems();
                    methodsToCallWhenIdle.Push( moveSelectedDown );
                }
                if( e.KeyCode == Keys.Up ) {
                    copyOfSelectedItems = this.createCopyOfSelectedItems();
                    methodsToCallWhenIdle.Push( moveSelectedUp );
                }
            }
        }
    
        List<ListItem> copyOfSelectedItems = new List<ListItem>();
        void moveSelectedDown() {
            if( copyOfSelectedItems.Count > 0 ) {
                boundList.MoveDown( copyOfSelectedItems );
                restoreSelection( copyOfSelectedItems );
            }
        }
        void moveSelectedUp() {
            if( copyOfSelectedItems.Count > 0 ) {
                boundList.MoveUp( copyOfSelectedItems );
                restoreSelection( copyOfSelectedItems );
            }
        }
    
        void restoreSelection( List<ListItem> selectedItems ) {
            foreach( ListItem item in selectedItems ) {
                listBox.SetSelected( listBox.Items.IndexOf( item ), true );
            }
        }
    
        List<ListItem> createCopyOfSelectedItems() {
            List<ListItem> result = new List<ListItem>();
            foreach( ListItem listItem in listBox.SelectedItems ) {
                result.Add( listItem );
            }
            return result;
        }
    
        void bindExampleDataToListBox() {
            BindingSource bSrc = new BindingSource();
            boundList = getExampleData();
            bSrc.DataSource = boundList;
            bSrc.Sort = "OrderValue DESC";
    
            listBox.DataSource = bSrc;
            listBox.DisplayMember = "TextValue";
    
        }
    
        ListItems getExampleData() {
            ListItems result = new ListItems();
            result.Add( new ListItem() { TextValue = "Item 1", OrderValue = 0 } );
            result.Add( new ListItem() { TextValue = "Item 5", OrderValue = 4 } );
            result.Add( new ListItem() { TextValue = "Item 3", OrderValue = 2 } );
            result.Add( new ListItem() { TextValue = "Item 4", OrderValue = 3 } );
            result.Add( new ListItem() { TextValue = "Item 2", OrderValue = 1 } );
            return result;
    
        }
    }
    

    我没有包括我对 ListItems 和 ListItem 的实现,因为它们与问题无关。但是,如果您想要它们的副本,请告诉我。

    【讨论】:

      【解决方案2】:

      您没有发布任何代码,但调用 e.SuppressKeyPress = true; 应该可以让它工作:

      void listBox1_KeyDown(object sender, KeyEventArgs e) {
        if (e.Control && e.KeyCode == Keys.Down) {
          e.SuppressKeyPress = true;
      
          if (listBox1.SelectedIndices.Count > 0 && 
              listBox1.SelectedIndices[listBox1.SelectedIndices.Count - 1] < listBox1.Items.Count-1) {
      
            List<int> selected = new List<int>();
            for (int i = 0; i < listBox1.SelectedIndices.Count; i++) {
              selected.Add(listBox1.SelectedIndices[i]);
            }
            listBox1.SelectedIndices.Clear();
      
            for (int i = selected.Count - 1; i >= 0; i--) {
              object listboxItem = listBox1.Items[selected[i] + 1];
              listBox1.Items[selected[i] + 1] = listBox1.Items[selected[i]];
              listBox1.Items[selected[i]] = listboxItem;
              listBox1.SelectedIndices.Add(selected[i] + 1);
            }
          }
        }
      }
      

      【讨论】: