3

List<>要素を上下に動かす最良の方法を教えてもらえますか?

たとえば、Buildingというクラスがあり、BuildingにはRoomsオブジェクトのリストがありますList<Room>。部屋は名前で建物に追加されていますが、私はこの構造を使用してツリービューを生成しています。ユーザーは、建物内で部屋を上下に移動するオプションがあります。

私は使おうとして.Reverse(index, count)いましたが、これは何もしなかったようです:

// can this item actually be moved up (is it at the first position in it's current parent?)
if (moveDirection == MoveDirection.UP)
{
    int roomIndex = parentBuilding.Rooms.IndexOf(room);

    if (roomIndex == 0)
    {
        return;
    }
    else
    {
        // move this room up.                            
        parentBuilding.Rooms.Reverse(roomIndex, 1);
    }
}
4

6 に答える 6

11

リスト拡張機能を作成します。として呼び出しますList<T>.Move(1, MoveDirection.Up)

public static class ListExtensions
{
    public static void Move<T>(this IList<T> list, int iIndexToMove, 
        MoveDirection direction)
    {

        if (direction == MoveDirection.Up)
        {
            var old = list[iIndexToMove - 1];
            list[iIndexToMove - 1] = list[iIndexToMove];
            list[iIndexToMove] = old;
        }
        else
        {
            var old = list[iIndexToMove + 1];
            list[iIndexToMove + 1] = list[iIndexToMove];
            list[iIndexToMove] = old;
        }
    }
}

public enum MoveDirection
{
    Up,
    Down
}

考慮事項

  • 例外処理 - 一番下の要素を下に、または一番上の要素を上に移動しようとしている場合はどうなりますか? これらを上下に移動できないため、範囲外のインデックスを取得します。

  • これを改善し、機能を拡張して上部要素を下部要素に移動し、下部要素を上部要素に移動するなどして、例外の処理を防ぐことができます。

于 2013-02-28T10:56:55.020 に答える
4

スワップを行うだけです:

int roomIndex = parentBuilding.Rooms.IndexOf(room);

if (roomIndex == 0)
{
    return;
}
else
{
    // move this room up.                            
    var temp = parentBuilding.Rooms[index-1];
    parentBuilding.Rooms[index-1] = parentBuilding.Rooms[index];
    parentBuilding.Rooms[index] = temp;
}
于 2013-02-28T10:57:37.547 に答える
1

個人的には、拡張メソッドを作成します。

static void Swap<TSource>(this IList<TSource> source, int fromIndex, int toIndex)
{
    if (source == null)
        throw new ArgumentNullExcpetion("source");

    TSource tmp = source[toIndex];
    source[toIndex] = source[fromIndex];
    source[fromIndex] = tmp;
}

使用法:

if (moveDirection == MoveDirection.UP)
{
    int roomIndex = parentBuilding.Rooms.IndexOf(room);

    if (roomIndex == 0)
    {
        return;
    }
    else
    {
        // move this room up.                            
        parentBuilding.Rooms.Swap(roomIndex, roomIndex - 1);
    }
}
于 2013-02-28T10:58:54.153 に答える
0

これを試して:

int newIndex = whateverIndexYouWantItAt;

int oldIndex = parentBuilding.Rooms.IndexOf(room);
var item = parentBuilding.Rooms[oldIndex];

list.RemoveAt(oldIndex);

if (newIndex > oldIndex) newIndex--; 

parentBuilding.Rooms.Insert(newIndex, item);
于 2013-02-28T10:55:59.867 に答える
0

上にあった部屋と場所を交換すると、次のようになります。

int roomIndex = parentBuilding.Rooms.IndexOf(room);

if (roomIndex == 0)
{
    return;
}

var wasAbove = parentBuilding.Rooms[roomIndex - 1];
parentBuilding.Rooms[roomIndex - 1] = room;
parentBuilding.Rooms[roomIndex] = wasAbove;

とはいえ、これが状況に最適なオブジェクト モデルであるかどうかはわかりません。リスト内の部屋の順序が役割を果たしていることは明らかではありません。また、部屋を「上に移動」する方法も明確ではありません。これはどういう意味ですか?

RoomPlacement部屋とその場所を特定するのに十分な情報を集約するクラスを用意し、代わりにそれを使用する方がよい場合があります。

于 2013-02-28T10:55:22.680 に答える
0

SortedDictionary<int, Room>リスト代わりに使ってみてはいかがでしょうか。インデックスをディクショナリのキーとして格納し、必要に応じて値を交換することができます。

于 2013-02-28T10:53:37.680 に答える