10

我有一个列表框,里面有一堆值。我还有一个向上按钮和一个向下按钮。使用这些按钮,我想向上/向下移动列表框中的选定项目。我很难做到这一点。

到目前为止,这是我的代码:

    private void btnDataUp_Click(object sender, RoutedEventArgs e)
    {

        int selectedIndex = listBoxDatasetValues.SelectedIndex; //get the selected item in the data list

        if (selectedIndex != -1 && selectedIndex != 0) //if the selected item is selected and not at the top of the list
        {
            //swap items here
            listBoxDatasetValues.SelectedIndex = selectedIndex - 1; //keep the item selected
        }


    }

我不知道如何交换值!任何帮助将不胜感激!

4

8 回答 8

26

由于您已通过使用 ItemsSource 绑定到 ObservableCollection 来填充列表框,因此您无法修改列表框的 Items 属性。

ItemsSource 只能在 Items 集合为空时设置,Items 只有在 ItemsSource 为空时才能修改。

否则您将收到错误“在使用 ItemsSource 时操作无效...”

您需要做的是修改底层集合,因为它是一个 ObservableCollection,所以 ListBox 将反映所做的更改。

以下代码显示了如何通过交换集合中的项目来上下移动项目。

相应的 XAML 只包含一个名为 lbItems 的列表框和 2 个连接事件处理程序的按钮。

public partial class MainWindow : Window
{
    private ObservableCollection<string> ListItems = new ObservableCollection<string>  
    { 
        "Item 1", "Item 2", "Item 3", "Item 4", "Item 5", "Item 6"
    };

    public MainWindow()
    {
        InitializeComponent();
        lbItems.ItemsSource = this.ListItems;
    }

    private void up_click(object sender, RoutedEventArgs e)
    {
        var selectedIndex = this.lbItems.SelectedIndex;

        if (selectedIndex > 0)
        {
            var itemToMoveUp = this.ListItems[selectedIndex];
            this.ListItems.RemoveAt(selectedIndex);
            this.ListItems.Insert(selectedIndex - 1, itemToMoveUp);
            this.lbItems.SelectedIndex = selectedIndex - 1;
        }
    }

    private void down_click(object sender, RoutedEventArgs e)
    {
        var selectedIndex = this.lbItems.SelectedIndex;

        if (selectedIndex + 1 < this.ListItems.Count)
        {
            var itemToMoveDown = this.ListItems[selectedIndex];
            this.ListItems.RemoveAt(selectedIndex);
            this.ListItems.Insert(selectedIndex + 1, itemToMoveDown);
            this.lbItems.SelectedIndex = selectedIndex + 1;
        }
    }
}
于 2012-09-22T10:08:29.640 回答
10

我为此做了一些扩展方法:

    public static void MoveItemUp<T>(this ObservableCollection<T> baseCollection, int selectedIndex)
    {
        //# Check if move is possible
        if (selectedIndex <= 0)
            return;

        //# Move-Item
        baseCollection.Move(selectedIndex - 1, selectedIndex);
    }

    public static void MoveItemDown<T>(this ObservableCollection<T> baseCollection, int selectedIndex)
    {
        //# Check if move is possible
        if (selectedIndex < 0 || selectedIndex + 1 >= baseCollection.Count)
            return;

        //# Move-Item
        baseCollection.Move(selectedIndex + 1, selectedIndex);
    }

    public static void MoveItemDown<T>(this ObservableCollection<T> baseCollection, T selectedItem)
    {
        //# MoveDown based on Item
        baseCollection.MoveItemDown(baseCollection.IndexOf(selectedItem));
    }

    public static void MoveItemUp<T>(this ObservableCollection<T> baseCollection, T selectedItem)
    {
        //# MoveUp based on Item
        baseCollection.MoveItemUp(baseCollection.IndexOf(selectedItem));
    }

无需为此了解 ListBox。

于 2014-01-24T10:09:06.730 回答
5

这是执行此操作的最简单方法,它会触发所有正确的事件,因此您不必担心 XAML。ObservableCollection 有一个很好的方法叫做

MoveItem(previousIndex, newIndex)

假设您有一个名为 DataItemList 的 ObservableCollection

public void MoveUp()
{
  var currentIndex = DataItemList.SelectedIndex;

  //Index of the selected item
  if (currentIndex > 0)
  {
    int upIndex = currentIndex - 1;

    //move the items
    DataItemList.MoveItem(upIndex,currentIndex);         
  }
}

对于 Down,您将获得前一项的索引。

就那么简单!

于 2013-01-25T21:00:52.523 回答
3

我会添加评论,但我不能,因为我只有 3 声望:/

Peter Hansen 的解决方案很棒,但是如果没有选中的元素,down_click 会抛出 ArgumentOutOfRange 异常。这是因为如果没有选择任何元素,则 Index 等于 -1。

我会像这样编辑 down_click :

private void down_click(object sender, RoutedEventArgs e)
{
    if (this.lbItems.SelectedIndex != -1) //Added condition
    {
        var selectedIndex = this.lbItems.SelectedIndex;
        if (selectedIndex + 1 < this.ListItems.Count)
        {
            var itemToMoveDown = this.ListItems[selectedIndex];
            this.ListItems.RemoveAt(selectedIndex);
            this.ListItems.Insert(selectedIndex + 1, itemToMoveDown);
            this.lbItems.SelectedIndex = selectedIndex + 1;
        }
    }
}
于 2013-09-27T06:58:58.920 回答
1
 if(listBoxDatasetValues.ListIndex > 0)
    {
        // add a duplicate item up in the listbox
        listBoxDatasetValues.AddItem(listBoxDatasetValues.Text, listBoxDatasetValues.ListIndex - 1);
        // make it the current item
        listBoxDatasetValues.ListIndex = (listBoxDatasetValues.ListIndex - 2);
        // delete the old occurrence of this item
        listBoxDatasetValues.RemoveItem(listBoxDatasetValues.ListIndex + 2);
    }
于 2012-09-22T04:25:01.863 回答
1

尝试这个:

if (listBoxDatasetValues.SelectedItems.Count > 0)
{
    object selected = listBoxDatasetValues.SelectedItem;
    int indx = listBoxDatasetValues.Items.IndexOf(selected);
    int totl = listBoxDatasetValues.Items.Count;

    if (indx == 0)
    {
        listBoxDatasetValues.Items.Remove(selected);
        listBoxDatasetValues.Items.Insert(totl - 1, selected);
        listBoxDatasetValues.SetSelected(totl - 1, true);
    }
    else{
        listBoxDatasetValues.Items.Remove(selected);
        listBoxDatasetValues.Items.Insert(indx - 1, selected);
        listBoxDatasetValues.SetSelected(indx - 1, true);
    }
}
于 2012-09-22T04:06:56.240 回答
0

你可以尝试这样的事情:

向上移动:

if (listboxName.SelectedIndex == -1 || listboxName.SelectedIndex == 0)
    return;

Object select, previous, temp;
select = listboxName.Items[listboxName.SelectedIndex];
previous = listboxName.Items[listboxName.SelectedIndex-1];

temp = select;
select = previous;
previous = temp;

listboxName.Items[listboxName.SelectedIndex] = select;
listboxName.Items[listboxName.SelectedIndex-1] = previous;

listboxName.SelectedIndex--;

向下移动:

if (listboxName.SelectedIndex == -1 || listboxName.SelectedIndex == listboxName.Items.Count-1)
    return;     

Object select, next, temp;
select = listboxName.Items[listboxName.SelectedIndex];
next = listboxName.Items[listboxName.SelectedIndex+1];

temp = select;
select = next;
next = temp;

listboxName.Items[listboxName.SelectedIndex] = select;
listboxName.Items[listboxName.SelectedIndex+1] = next;

listboxName.SelectedIndex++;
于 2012-09-22T03:45:06.703 回答
0

无需使用可观察集合,您只需依靠 ListBox 内的集合对象就可以更简单,这是@Peter Hansen 答案的优化版本:

private void up_click(object sender, RoutedEventArgs e)
{
    var selectedIndex = this.lbItems.SelectedIndex;

    if (selectedIndex > 0)
    {
        var itemToMoveUp = this.lbItems.Items[selectedIndex];
        this.lbItems.Items.RemoveAt(selectedIndex);
        this.lbItems.Items.Insert(selectedIndex - 1, itemToMoveUp);
        this.lbItems.SelectedIndex = selectedIndex - 1;
    }
}

private void down_click(object sender, RoutedEventArgs e)
{
    var selectedIndex = this.lbItems.SelectedIndex;

    if (selectedIndex + 1 < this.lbItems.Items.Count)
    {
        var itemToMoveDown = this.lbItems.Items[selectedIndex];
        this.lbItems.Items.RemoveAt(selectedIndex);
        this.lbItems.Items.Insert(selectedIndex + 1, itemToMoveDown);
        this.lbItems.SelectedIndex = selectedIndex + 1;
    }
}
于 2020-10-16T16:55:17.067 回答