0

つまり、 ListBox.Itemsの 2 つの隣接要素を交換する方法は?

詳細は次のとおりです。

私は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;
    }
}

リストの 2 つの要素の順序を入れ替えたい:

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

このようなスワップを実行した後、に値を割り当てると、正しくない動作が得られます。UIStringListSelectedItemのいくつかのアイテムが選択されています
が、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 に答える