プロが教えるわが家の防犯対策術!

C#、listboxについての質問です。

二つのリストボックスがあるとします。
・listBox1
・listBox2

listBox1にはアイテムが複数セットされている状態です。
アイテムが選択されいている状態でrightbuttonをクリックすると
listBox2にアイテムが移動します(lisytBox1でそのアイテムはremove)

もしかしたら間違えてlistBox2に移動する可能性もあるので2から1へ
アイテムを戻すlefghtbuttonも用意します。

そこで質問です。
そのときに2から1へ戻ったとき、普通にAdd()するのではなく、移動する前の状態の位置に戻したいのです。

普通にやると末端に追加されます。

ロジックが思いつきません。
お力添えのほどよろしくお願いいたします。

A 回答 (4件)

listBox1に追加するオブジェクトに,本来の並び順を保持させておいて,


戻す時にはオブジェクトの並び順を見てInsertする位置を決めればよいでしょう。

ListBoxに追加できるのは文字列だけでなく,どんなオブジェクトでも追加できます。
また,要素の表示はListBoxのDisplayMemberで決定されますが,DisplayMemberを指定していない場合はToStringが使われます。

なので,
class Item : IComparable<Item>
{
public Item (string display, int defaultOrder)
{
Display = display;
DefaultOrder = defaultOrder;
}

public string Display { get; private set; }
public int DefaultOrder { get; private set; }

int IComparable<Item>.CompareTo (Item other)
{
if (other == null) { return 1; }
return DefaultOrder.CompareTo(other.DefaultOrder);
}

public override string ToString ()
{
return Display;
}
}
というようなクラスを作り,このItemクラスをlistBox1, listBox2の要素としておけば,
var pos = listBox1.Items.Cast<Item>().ToList().BinarySearch(addItem);
if (pos < 0) { pos = ~pos; }
listBox1.Items.Insert(pos, addItem);
で戻すことができます。
    • good
    • 0

というワケで…簡単に作ってみました。


検証不十分と思われますので、地道に検証してくださいな。

ちなみに、プロパティでbutton1(rightbutton相当)とbutton2(lefghtbutton相当)のEnabledはfalseに、
listBox1のItemsにはあらかじめデータ入れておいてください。
あと、全角空白でインデントしていますのでよろしく処理してください。
コメントも特に入れていないので自力で読んでください。

public partial class Form1 : Form
{
 private Stack<MoveItemHistory> History;
 public Form1()
 {
  InitializeComponent();
  History = new Stack<MoveItemHistory>();
 }
 private void button1_Click(object sender, EventArgs e)
 {
  MoveItemHistory temp = new MoveItemHistory();

  temp.Index = listBox1.SelectedIndex;
  temp.ItemString = (string)listBox1.Items[temp.Index];
  listBox2.Items.Add(temp.ItemString);
  listBox1.Items.RemoveAt(temp.Index);
  listBox1.SelectedIndex = -1;
  History.Push(temp);
  button2.Enabled = true;
 }
 private void button2_Click(object sender, EventArgs e)
 {
  MoveItemHistory temp = History.Pop();

  button2.Enabled = (History.Count > 0);
  listBox2.Items.Remove(temp.ItemString);
  listBox1.Items.Insert(temp.Index, temp.ItemString);
 }
 private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
 {
  button1.Enabled = (listBox1.SelectedIndex != -1);
 }
}
public class MoveItemHistory
{
 public int Index;
 public string ItemString;
}
    • good
    • 0

>そうするとlistBox1の5番目[りんご]


>をlistBox2に移動し、他のアイテムも複数移動したら
>listBox1の配列のCountは(例えば)2つとかになりますよね。
>listBox2からlistBox1に戻すときに5番目、(移動するときに持っていたindex=5)にインサートしたら、配列範囲外になりませんか?

だから、「最後の1つだけ…とか制限付くと思いますけども。」と書いたのですが……。

そういう制限なしでやりたいというのであれば、履歴を持ち続けるしかないでしょうね。
で、lefghtbuttonのたびに履歴から操作することに。
# 履歴を格納する構造体なり作って、List構造として記録…でしょうかねぇ。
# List<T>とかで。
# スタック構造でもいいのか…そういうのがあったかはちょっと不明ですが。
# 「C# アンドゥ 実装」辺りで検索するとよさげなものが見つかるかも知れませんね。
    • good
    • 0

>そこで質問です。


>そのときに2から1へ戻ったとき、普通にAdd()するのではなく、移動する前の状態の位置に戻したいのです。

ListBox.Items.Insert()ですかね。

最後の1つだけ…とか制限付くと思いますけども。
rightbuttonで移動(というかlistBox1から削除)する前にインデックスを記憶…
lefghtbuttonで戻す時に記録していたインデックスを元にInsert()
ってところでしょうかね。

listBox1の先頭のアイテムや最後のアイテムだった場合に正しく動作するか?
というのはちゃんと確認してくださいな。

この回答への補足

listBox1の総数を5こだとします。
そうするとlistBox1の5番目[りんご]
をlistBox2に移動し、他のアイテムも複数移動したら
listBox1の配列のCountは(例えば)2つとかになりますよね。
listBox2からlistBox1に戻すときに5番目、(移動するときに持っていたindex=5)にインサートしたら、配列範囲外になりませんか?

また、listbox1から2へいくつか移動した後から戻したとすると、
indexは混同しませんか?

という感じで悩んでおります。。。
未熟者故、うまいロジックが思いつかないのです。

せっかく教えて下さったのですが、今一度お力添えをお願いいたします><

補足日時:2014/08/20 16:31
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!