0

简而言之,如何交换ListBox.Items的两个相邻元素?

详情如下。

我使用 WPF 列表框。
(我使用 MVVM 模式——对于这个问题来说没有那么重要,只是为了清楚起见)

我使用以下 XAML 定义定义 ListBox:

    <ListBox Name="listBox1" 
             DisplayMemberPath="Value" 
             ItemsSource="{Binding StringList}"
             SelectedIndex="{Binding StringListSelectedItem}" />

视图模型代码片段如下:

    public ObservableCollection<StringWrapper> StringList {get; set;}

    private int stringListSelectedItem;

    public int StringListSelectedItem
    {
        get {return stringListSelectedItem;}
        set {
            stringListSelectedItem = value;
            NotifyPropertyChanged("StringListSelectedItem");
        }
    }

StringWrapper只是一个小类,以避免列表框中的相同字符串值出现问题:

public class StringWrapper
{
    public string Value { get; private set; }

    public StringWrapper(string v)
    {
        Value = v;
    }
}

我想交换列表中两个元素的顺序:

        StringWrapper tmp = StringList[index];
        StringList[index] = StringList[index - 1];
        StringList[index - 1] = tmp;

执行此类交换后,我在为 赋值时获得了不正确的行为StringListSelectedItem:选择了 UI 中的几个项目,
但是listBox1.SelectionMode == Single.
此外,当我在调试器中检查变量值时,一切看起来都很好,但是在窗口中,当我运行应用程序时,我看到ListBox.

可以通过在交换后执行以下代码来修复它:

        for (int i = 0; i < vm.StringList.Count(); i++) 
            listBox1.SelectedIndex = i;

但是每次都遍历所有项目并不是一个好主意,当我只需要设置选定的项目时。

我的代码有什么问题?它会破坏某些东西吗?如何获得正确的行为SelectedIndex
谢谢。

4

3 回答 3

1

而不是这个:

    StringWrapper tmp = StringList[index];
    StringList[index] = StringList[index - 1];
    StringList[index - 1] = tmp;

试试这个:

    StringWrapper tmp = StringList[index];
    StringList.RemoveAt(index);
    StringList.Insert(index-1,tmp);
于 2012-07-19T18:02:28.157 回答
0

您提供选择模式的代码未设置为单一。您确定在您的应用程序中设置正确吗?如果是这样,您是在代码后面还是实际上在 XAML 中设置选择模式?如果它在后面的代码中,我怀疑数据绑定/选择项在启动时发生,然后设置选择模式的代码运行。为了安全起见,在 xaml 中设置选择模式以及绑定。

还尝试使用绑定路径而不是绑定,例如:

<ListBox Name="listBox1" 
             DisplayMemberPath="Value" 
             ItemsSource="{Binding StringList}"
             SelectedItem="{Binding Path=StringListSelectedItem, Mode=TwoWay}"
             SelectionMode="Single"/>
于 2012-07-19T17:59:07.680 回答
0

您可以尝试为内置的 ObservableCollection 使用一个小的扩展,以确保当集合中的一个项目发生更改时,所有其他项目也会得到通知。

使用这个子类:

public class ExtednedObservableCollection<T> : ObservableCollection<T> {

    public ExtednedObservableCollection()
        : base() {

        this.CollectionChanged += new NotifyCollectionChangedEventHandler(OnCollectionChanged);
    }

    private void OnCollectionChanged(object o, NotifyCollectionChangedEventArgs e) {


        if (e.NewItems != null) {

            foreach (Object item in e.NewItems) {

                (item as INotifyPropertyChanged).PropertyChanged += new PropertyChangedEventHandler(item_PropertyChanged);
            }
        }

        if (e.OldItems != null) {

            foreach (Object item in e.OldItems) {

                (item as INotifyPropertyChanged).PropertyChanged -= new PropertyChangedEventHandler(item_PropertyChanged);
            }
        }
    }

    void item_PropertyChanged(object sender, PropertyChangedEventArgs e) {

        NotifyCollectionChangedEventArgs a = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset);
        OnCollectionChanged(a);
    }

}
于 2012-07-19T18:09:50.853 回答