C#, listBoxのItem追加についての質問

このQ&Aのポイント
  • C#のlistBoxでアイテムを追加する方法について質問があります。
  • 二つのリストボックスがあり、rightbuttonをクリックすると選択されたアイテムがlistBox2に移動します。
  • 移動したアイテムをlistBox1に戻す際、元の位置に戻す方法が分かりません。お力添えいただけますでしょうか。
回答を見る
  • ベストアンサー

C#,listBoxのItem追加についての質問

C#、listboxについての質問です。 二つのリストボックスがあるとします。 ・listBox1 ・listBox2 listBox1にはアイテムが複数セットされている状態です。 アイテムが選択されいている状態でrightbuttonをクリックすると listBox2にアイテムが移動します(lisytBox1でそのアイテムはremove) もしかしたら間違えてlistBox2に移動する可能性もあるので2から1へ アイテムを戻すlefghtbuttonも用意します。 そこで質問です。 そのときに2から1へ戻ったとき、普通にAdd()するのではなく、移動する前の状態の位置に戻したいのです。 普通にやると末端に追加されます。 ロジックが思いつきません。 お力添えのほどよろしくお願いいたします。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.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); で戻すことができます。

その他の回答 (3)

  • Wr5
  • ベストアンサー率53% (2177/4070)
回答No.3

というワケで…簡単に作ってみました。 検証不十分と思われますので、地道に検証してくださいな。 ちなみに、プロパティで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; }

  • Wr5
  • ベストアンサー率53% (2177/4070)
回答No.2

>そうするとlistBox1の5番目[りんご] >をlistBox2に移動し、他のアイテムも複数移動したら >listBox1の配列のCountは(例えば)2つとかになりますよね。 >listBox2からlistBox1に戻すときに5番目、(移動するときに持っていたindex=5)にインサートしたら、配列範囲外になりませんか? だから、「最後の1つだけ…とか制限付くと思いますけども。」と書いたのですが……。 そういう制限なしでやりたいというのであれば、履歴を持ち続けるしかないでしょうね。 で、lefghtbuttonのたびに履歴から操作することに。 # 履歴を格納する構造体なり作って、List構造として記録…でしょうかねぇ。 # List<T>とかで。 # スタック構造でもいいのか…そういうのがあったかはちょっと不明ですが。 # 「C# アンドゥ 実装」辺りで検索するとよさげなものが見つかるかも知れませんね。

  • Wr5
  • ベストアンサー率53% (2177/4070)
回答No.1

>そこで質問です。 >そのときに2から1へ戻ったとき、普通にAdd()するのではなく、移動する前の状態の位置に戻したいのです。 ListBox.Items.Insert()ですかね。 最後の1つだけ…とか制限付くと思いますけども。 rightbuttonで移動(というかlistBox1から削除)する前にインデックスを記憶… lefghtbuttonで戻す時に記録していたインデックスを元にInsert() ってところでしょうかね。 listBox1の先頭のアイテムや最後のアイテムだった場合に正しく動作するか? というのはちゃんと確認してくださいな。

halziiin
質問者

補足

listBox1の総数を5こだとします。 そうするとlistBox1の5番目[りんご] をlistBox2に移動し、他のアイテムも複数移動したら listBox1の配列のCountは(例えば)2つとかになりますよね。 listBox2からlistBox1に戻すときに5番目、(移動するときに持っていたindex=5)にインサートしたら、配列範囲外になりませんか? また、listbox1から2へいくつか移動した後から戻したとすると、 indexは混同しませんか? という感じで悩んでおります。。。 未熟者故、うまいロジックが思いつかないのです。 せっかく教えて下さったのですが、今一度お力添えをお願いいたします><

関連するQ&A

  • リストボックスのアイテムをマウスで並べ替えたいです

    リストボックスのアイテムをマウスのドラッグドロップで並べ替えたいのですが、 下のような感じで書いてみたのですが、 この状態だと、4番目のものを一番上に持ってくるという動作だけするのですが、 4番目から3番目に移動する場合や、1番目から3番目に移動する場合など 追加していくとIFが重なってきてすごくややこしくなってしまいます。 もっと分かりやすくて合理的な方法がありましたら、 大体でも良いですので、教えて頂けたら助かります。 よろしくおねがいいたします。 Private Sub Form1_Load(...略 ListBox1.Items.Add("AAA") ListBox1.Items.Add("BBB") ListBox1.Items.Add("CCC") ListBox1.Items.Add("EEE") End Sub Private Sub ListBox1_MouseDown(...略 SelectedSortFrom = ListBox1.SelectedIndex End Sub Private Sub ListBox1_MouseUp(...略 SelectedSortTo = ListBox1.SelectedIndex ListBox1Sort(SelectedSortFrom, SelectedSortTo) End Sub Private Function ListBox1Sort(ByVal From As Integer, ByVal Too As Integer) If From = -1 Then Exit Function If Too = -1 Then Exit Function Dim A(ListBox1.Items.Count) As String Dim B As Boolean For i As Integer = 0 To ListBox1.Items.Count - 1 A(i) = ListBox1.Items(i) Next For i As Integer = 0 To ListBox1.Items.Count - 1 If i = Too Then ListBox1.Items(i) = A(From) B = True Else ListBox1.Items(i) = A(i - 1) End If Next End Function

  • listBoxとTimerについて C#

    listBoxとTimerについて C# ヤフーニュースのURLをlistboxへ入れます。 そしてlistBox1の中身を画面表示させたら、次にlistBox2の中身も表示したいと思っています。 最初listBoxが1つだったときはうまく行っていたのですが、listBoxを増やすとうまく行かなくなりました。 この状態だと、listBox2の中身だけ表示させて終わってしまいます。 Timerの使い方が怪しいと思うのですが、どうでしょうか? 些細なことでも何でもいいのでご意見頂ければ助かります。 -----以下コード抜粋------ public partial class Form1 : Form { public Form1() { InitializeComponent(); } int urlindex = 0; private void Form1_Load(object sender, EventArgs e) { listBox1.AllowDrop = true; listBox1.DragEnter += new DragEventHandler(listBox1_DragEnter); listBox1.DragDrop += new DragEventHandler(listBox1_DragDrop); listBox2.AllowDrop = true; listBox2.DragEnter += new DragEventHandler(listBox2_DragEnter); listBox2.DragDrop += new DragEventHandler(listBox2_DragDrop); } private void listBox1_DragEnter(object sender, DragEventArgs e) { //URLのみ受け入れる//@ITより if (e.Data.GetDataPresent("UniformResourceLocator")) e.Effect = DragDropEffects.Link; else e.Effect = DragDropEffects.None; } private void listBox2_DragEnter(object sender, DragEventArgs e) { //URLのみ受け入れる//@ITより if (e.Data.GetDataPresent("UniformResourceLocator")) e.Effect = DragDropEffects.Link; else e.Effect = DragDropEffects.None; } private void listBox1_DragDrop(object sender, DragEventArgs e) { //ドロップされたリンクのURLを取得する//@ITより string url = e.Data.GetData(DataFormats.Text).ToString(); //結果を表示 listBox1.Text = url; //MessageBox.Show(url); //ドロップされたデータがstring型か調べる if (e.Data.GetDataPresent(typeof(string))) { ListBox target = (ListBox)sender; //ドロップされたデータ(string型)を取得 string itemText = (string)e.Data.GetData(typeof(string)); //ドロップされたデータをリストボックスに追加する target.Items.Add(url); //MessageBox.Show("表示"); } } private void listBox2_DragDrop(object sender, DragEventArgs e) { //ドロップされたリンクのURLを取得する//@ITより string url = e.Data.GetData(DataFormats.Text).ToString(); //結果を表示 listBox2.Text = url; //MessageBox.Show(url); //ドロップされたデータがstring型か調べる if (e.Data.GetDataPresent(typeof(string))) { ListBox target = (ListBox)sender; string itemText = (string)e.Data.GetData(typeof(string)); target.Items.Add(url); } } private void goButton_Click(object sender, EventArgs e) { urlindex = 0; timer1.Start(); timer2.Start(); } private void timer1_Tick(object sender, EventArgs e) { timer1.Stop(); if (listBox1.Items.Count != 0 && urlindex < listBox1.Items.Count) { string url = (string)listBox1.Items[urlindex]; webBrowser1.Navigate(url); urlindex++; } } private void timer2_Tick_1(object sender, EventArgs e) { timer2.Stop(); if (listBox2.Items.Count != 0 && urlindex < listBox2.Items.Count) { string url = (string)listBox2.Items[urlindex]; } } private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) { timer1.Start(); timer2.Start(); } private void listBox2_SelectedIndexChanged(object sender, EventArgs e) { }

  • ListBoxのBackColor変更

    EXCEL2007のVBAにて質問です。 ユーザーフォームにリストボックスを配置して、選んだ物によって リストボックスの背景色を変更しようとしているのですが、うまくいきません。 例えばlistbox1を以下の様にセットし、 Private Sub UserForm_Initialize() UserForm1.ListBox1.AddItem ("ピンク") UserForm1.ListBox1.AddItem ("白") End Sub 下記の通り選んだ項目で背景色を変えたいのですが、 Private Sub ListBox1_Click() '選んだ項目で色変え If UserForm1.ListBox1.ListIndex = 0 Then UserForm1.ListBox1.BackColor = RGB(255, 128, 128) 'ピンクなら背景をピンクに Else UserForm1.ListBox1.BackColor = RGB(255, 255, 255) '白なら背景を白に End If End Sub クリックして項目を選択しても背景の色が変わりません。 何か見落としている事があるでしょうか? 又はやり方が悪いのでしょうか? お教え頂けると助かります。 以上、宜しくお願い申し上げます。

  • リストアイテムの更新

    リストボックスのアイテムの更新はLB_DELETESTRINGで消してからインサートしていますが、消さずに更新するものは用意されていませんか?

  • excel vba listboxについて

    EXCELのVBA LISTBOXに関することで質問です。 ワークシート1のA2-5セルに取引先名を入力してあります。 UF1という名前のユーザーフォームの中にリストボックスを作成し、ワークシート1のA2-5の取引先を表示するには、 Private Sub UserForm_Initialize() Dim torihiki As String torihiki = Worksheets(1).range("A2:A5") UF1.ListBox1.List() = torihiki End Sub と打ち込んでいます。 ちなみに、ユーザーフォームは以下のようにOKボタンで閉じるようにしました。 Private Sub CommandBottan1_Click() unload UF1 End Sub 質問したいのはここからですが、 上のユーザーフォーム内のリストボックスで選択された取引先をTRHKという変数に代入したい場合、どうしたらいいのでしょうか? 私の少ない知識を振り絞って以下のように考えてみたのですが、 TRHK = UF1.ListBox1.List() としても代入されていないようです。 List()ではないメソッドが必要なのだと思うのですが・・・・ .Selectedとかでしょうか? どなたか、ご教授願います! 宜しくお願い致します。

  • Delphi .net ListBoxで上下キーで移動したい

    Delphi .net WEB版での作成です。 LISTBOXを作成するソースがあります。 --- while 条件 do begin LstBox1.Items.Insert(Row,Text); LstList.Items.Item[Row].value := LstValue; end; --- リストボックスは作成されますが、 上下キーで項目の移動ができません。 この作成をPage_Load の度に行えばできるのですが 作成処理は重いので、作成は1回のみで行いたいです。 どのようにすればよろしいのでしょうか?

  • EXCELのVBAでリストボックスに関して質問させていただきます。

    EXCELのVBAでリストボックスに関して質問させていただきます。 UserForm上にListBox1とListBox2を横並びに並べてあります。 ListBox1とListBox2に表示されているデータの行数は同じです。 この時、ListBox1のスライドバーを動かすとListBox2も同時に動くようにしたいのですが可能でしょうか?

  • リスト間のアイテム移動について

    現在独学でhttp://www4.plala.or.jp/tamo/vb/vb99.htmlの問題の10番を解いてるのですが、どうしてもうまくいきません。 左のリストボックスから右のリストボックスへの1つ1つのアイテム移動はできたのですが、アイテムを複数同時に選択すると違うアイテムが移動したりすべてのアイテムが移動してしまいます。 今のコードは Private Sub Command1_Click() For i = List1.ListCount To 1 Step -1 If List1.Selected(i - 1) = True Then List2.AddItem List1.Text List1.RemoveItem List1.ListIndex End If Next End Sub Private Sub Form_Load() With List1 .AddItem "FreeBSD" .AddItem "Linux" .AddItem "Macintosh" .AddItem "MS-DOS" .AddItem "Slaris" .AddItem "Windows 95" .AddItem "Windows CE" .AddItem "Windows NT" End With End Sub このように指定しています。 解決法がありましたら教えてください。

  • ボタンをクリックしても空白をリストに追加しないようにしたい

    初心者ですのでよろしくお願いいたします。 以下のようなコードでボタンを押すとテキストボックスに入力してあるテキストをリストに登録したいのですが、空白の場合は追加したくありません。どのように書けばいいでしょうか? よろしくお願いいたします。 (ちなみにLabel3にはリストに登録された数が出ます) Public Class Form1 Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click End End Sub Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click ListBox1.Items.Add(TextBox1.Text) TextBox1.Clear() Label3.Text = ListBox1.Items.Count End Sub Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click ListBox1.Items.Remove(ListBox1.SelectedItem) Label3.Text = ListBox1.Items.Count End Sub End Class

  • 複数の条件で、csvファイル内から表示させたい。

    ボタンを押すと、テキストボックス・コンボボックスの文字を読み取って、 用意してあるcsvファイルから、一致するデータをリストボックスに表示できるようにしようとしています。 If (A = TextBox1.Text) And ・・・(F = ComboBox1.SelectedItem)Then G = Items(0) & ・・・  Items(5) Me.ListBox1.Items.Add(G) こんな感じで「=」と「<>」を使って、考えられる全ての組み合わせで書いたのですが、思ったように表示されず困っています。 ボタンを押すと、AとBが両方とも一致しないと表示してほしくないのに、 Aに一致するものとBに一致するものがリストボックスに出てくる状態です。 色々とやってみたのですが、どれもうまくいかず、 私の考え方だとできない気がしたので、質問させていただきました。 どなたか、分かりやすく教えていただけませんか?

専門家に質問してみよう