質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.48%

  • C#

    7413questions

    C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

  • Android

    6628questions

    Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

  • Visual Studio

    1903questions

    Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

  • Xamarin

    518questions

    Xamarin(ザマリン)は、iPhoneなどのiOSやAndroidで動作し、C# 言語を用いてアプリを開発できるクロスプラットフォーム開発環境です。Xamarin Studioと C# 言語を用いて、 iOS と Android の両方の開発を行うことができます。

Xamarin - ExpandableListViewのリスト追加

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 177

Yu_N

score 13

XamarinのExpandableListViewの親リストを後から追加し更新させたいのですが、どのように書けばいいのでしょうか?
追加する親リストの名前はダイアログで入力させています。

                notebutton.Click += (_, __) =>
                {
                    var layout = new LinearLayout(this) { Orientation = Orientation.Vertical };
                    layout.SetGravity(GravityFlags.Left);
                    var notename = new EditText(this);
                    layout.AddView(new TextView(this) { Text = "ノート名" });
                    layout.AddView(notename);

                    var dlg = new AlertDialog.Builder(this);
                    dlg.SetTitle("ノートの名前を入力してください。");
                    dlg.SetView(layout); //<=作成したビューを指定

                    dlg.SetPositiveButton("OK", (s, a) => Toast.MakeText(this, notename.Text, ToastLength.Short).Show());
                    dlg.Create().Show();

                    //リスト追加、更新
                    groupElement.Add(notename.Text);
                    groupList.Add(groupElement);
                    adapter.NotifyDataSetChanged();

                };

全体コード

using Android.App;
using Android.Widget;
using Android.OS;
using System.Collections.Generic;
using Android.Content;
using PCLStorage;
using Android.Runtime;
using Temo1.Resources.layout;
using Android.Views;
using static Android.Resource;

namespace Temo1
{
    [Activity(Label = "Temo1", MainLauncher = true)]
    public class MainActivity : Activity
    {
        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);

            // Set our view from the "main" layout resource
            SetContentView(Resource.Layout.Main);



            Button memobutton = FindViewById<Button>(Resource.Id.button1);
            Button notebutton = FindViewById<Button>(Resource.Id.notebutton);
            ExpandableListView memolist = FindViewById<ExpandableListView>(Resource.Id.expandableListView1);

            string[] filename = new string[100];
            int n;
            var localFolder = FileSystem.Current.LocalStorage;
            var files = localFolder.GetFilesAsync().Result;


            //親リストgroupList子リストchildList
            List<IDictionary<string, object>> groupList = new List<IDictionary<string, object>>();
            List<IList<IDictionary<string, object>>> childList = new List<IList<IDictionary<string, object>>>();

            //デフォルトのグループ"全て"
            JavaDictionary<string, object> groupElement = new JavaDictionary<string, object>();
            groupElement.Add("GROUP_TITLE", "ALL");
            groupList.Add(groupElement);





            //子リスト用の文字列(ファイル名)を配列に用意
            n = 0;
            foreach (var file in files)
            {
                var fn = file.Name;
                fn = fn.Remove(fn.Length - 4);//拡張子を表示しないように末尾を削除
                filename[n] = fn;//配列にファイル名を格納
                n++;
            }


            JavaList<IDictionary<string, object>> childElements = new JavaList<IDictionary<string, object>>();
            for (int j = 0; j <= n - 1; j++)
            {
                JavaDictionary<string, object> child = new JavaDictionary<string, object>();
                child.Add("CHILD_TITLE", filename[j]);
                childElements.Add(child);
            }
            childList.Add(childElements);

            SimpleExpandableListAdapter adapter = new SimpleExpandableListAdapter(
                                          this,
                                          groupList,
                                          Android.Resource.Layout.SimpleExpandableListItem1,
                                          new string[] { "GROUPE_TITLE" },
                                          new int[] { Android.Resource.Id.Text1 },
                                          childList,
                                          Android.Resource.Layout.SimpleExpandableListItem2,
                                          new string[] { "CHILD_TITLE" },
                                          new int[] { Android.Resource.Id.Text2 }
                                          );
            memolist.SetAdapter(adapter);


            //親リスト追加

            //リスト名入力ダイアログ
            notebutton.Click += (_, __) =>
            {
                var layout = new LinearLayout(this) { Orientation = Orientation.Vertical };
                layout.SetGravity(GravityFlags.Left);
                var notename = new EditText(this);
                notename.SetMaxLines(1);
                layout.AddView(new TextView(this) { Text = "ノート名" });
                layout.AddView(notename);

                var dlg = new AlertDialog.Builder(this);
                dlg.SetTitle("ノートの名前を入力してください。");
                dlg.SetView(layout); //<=作成したビューを指定

                dlg.SetPositiveButton("OK", (s, a) =>
                {
                    Toast.MakeText(this, notename.Text, ToastLength.Short).Show();

                    if (!string.IsNullOrEmpty(notename.Text))
                    {
                        var newGroupElement = new JavaDictionary<string, object>();
                        newGroupElement.Add("GROUPE_LIST", notename.Text);
                        groupList.Add(newGroupElement);
                        adapter.NotifyDataSetChanged();
                    }
                    else
                    {
                        // 未入力エラー
                    }
                });
                dlg.Create().Show();


                };


            //メモ作成画面へ遷移
            memobutton.Click += (_, __) =>

            {

                var intent = new Intent(this, typeof(memocreate));

                StartActivity(intent);


            };


            //リストアイテムがクリックされたらテキスト編集に遷移
            memolist.ChildClick+= async (sender, e) =>
            {
                var parent = (ExpandableListView)e.Parent;
                var packedPosition = parent.GetExpandableListPosition(e.ChildPosition);

                var groupPosition = ExpandableListView.GetPackedPositionGroup(packedPosition);
                var childPosition = ExpandableListView.GetPackedPositionChild(packedPosition);
                var type = ExpandableListView.GetPackedPositionType(packedPosition);
                if (type == PackedPositionType.Child)
                {
                    var item = (IDictionary<string, object>)parent.ExpandableListAdapter.GetChild(groupPosition, childPosition+1);
                    var clickfile = item["CHILD_TITLE"].ToString();

                    //そのファイルのテキストを取得
                    IFolder rootFolder = FileSystem.Current.LocalStorage;
                    IFile file = await rootFolder.GetFileAsync(clickfile + ".txt");
                    string saveddata = await file.ReadAllTextAsync();

                    var intent = new Intent(this, typeof(memoedit));
                    intent.PutExtra("clickfile", clickfile); 
                    intent.PutExtra("Data", saveddata);


                    StartActivity(intent);

                }
            };



                //長押しされたアイテムを削除
                memolist.ItemLongClick += async (sender, e) =>
            {
                var parent = (ExpandableListView)e.Parent;
                var packedPosition = parent.GetExpandableListPosition(e.Position);

                var groupPosition = ExpandableListView.GetPackedPositionGroup(packedPosition);
                var childPosition = ExpandableListView.GetPackedPositionChild(packedPosition);
                var type = ExpandableListView.GetPackedPositionType(packedPosition);
                if (type == PackedPositionType.Child)
                {
                    var item = (IDictionary<string, object>)parent.ExpandableListAdapter.GetChild(groupPosition, childPosition);
                    var deletefile = item["CHILD_TITLE"].ToString();


                    //adapterから削除し更新
                    childList[groupPosition].Remove(item);
                    adapter.NotifyDataSetChanged();

                    //元ファイル削除
                    IFolder rootFolder = FileSystem.Current.LocalStorage;
                    IFile file = await rootFolder.GetFileAsync(deletefile + ".txt");

                    await file.DeleteAsync();
                }


            };




















        }
    }
}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • ppn

    2018/10/22 12:33

    xamarinは日本語のリソースに乏しいので、英語で調べるとよいかもです。

    キャンセル

回答 1

checkベストアンサー

+1

groupListに追加しても表示が変わらないのであれば、groupListの型がJavaListになっていないのではないでしょうか?
また、groupListに追加するgroupElementは新しくオブジェクトを作成しなければいけません。

dlg.SetPositiveButton("OK", (s, a) => 
{
    Toast.MakeText(this, notename.Text, ToastLength.Short).Show();

    if (!string.IsNullOrEmpty(notename.Text))
    {
        var newGroupElement = new JavaDictionary<string, object>();
        newGroupElement.Add("GROUPE_TITLE", notename.Text);
        groupList.Add(newGroupElement);
        adapter.NotifyDataSetChanged();
    }
    else
    {
        // 未入力エラー
    }
});

あと、ダイアログで入力した値を使うのであれば、この処理は、SetPositiveButtonhandler内でやるべきです。


リストデータの保存は、OnSaveInstanceStatePutSerializableで行い、OnCreateで、GetSerializableで取得します。

    public class MainActivity : Activity
    {
        private JavaList<IDictionary<string, object>> groupList;
        private JavaList<IList<IDictionary<string, object>>> childList;

        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);

            // Set our view from the "main" layout resource
            SetContentView(Resource.Layout.Main);

            ...

            if (savedInstanceState != null)
            {
                groupList = savedInstanceState.GetSerializable(nameof(groupList)).JavaCast<JavaList<IDictionary<string, object>>>();
                childList = savedInstanceState.GetSerializable(nameof(childList)).JavaCast<JavaList<IList<IDictionary<string, object>>>>();
            }
            else
            {
                groupList = new JavaList<IDictionary<string, object>>();
                childList = new JavaList<IList<IDictionary<string, object>>>();

                ...
            }

            SimpleExpandableListAdapter adapter = new SimpleExpandableListAdapter(
                                          this,
                                          groupList,
                                          Android.Resource.Layout.SimpleExpandableListItem1,
                                          new string[] { "GROUPE_TITLE" },
                                          new int[] { Android.Resource.Id.Text1 },
                                          childList,
                                          Android.Resource.Layout.SimpleExpandableListItem2,
                                          new string[] { "CHILD_TITLE" },
                                          new int[] { Android.Resource.Id.Text2 }
                                          );
            memolist.SetAdapter(adapter);

            ...
        }

        protected override void OnSaveInstanceState(Bundle outState)
        {
            base.OnSaveInstanceState(outState);

            outState.PutSerializable(nameof(groupList), groupList.JavaCast<ISerializable>());
            outState.PutSerializable(nameof(childList), childList.JavaCast<ISerializable>());
        }
    }

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/10/29 11:17 編集

    groupListの型はJavaListになっていましたが、うまくいきませんでした。。。

    キャンセル

  • 2018/10/29 11:40

    回答のコードを修正しました

    キャンセル

  • 2018/10/29 11:45

    ありがとうございます!返信をお持ちしている間に自己解決できました。
    このコードでもトーストが出るだけでグループが追加されないのですが、どこのコードに問題があるか分かりますか?

    キャンセル

  • 2018/10/29 11:57

    ExpandableListViewを使っているActivityのコード全体を記載してもらえますか?

    キャンセル

  • 2018/10/29 12:06

    質問文に追記しました。よろしくお願いします<m(__)m>

    キャンセル

  • 2018/10/29 12:18

    記載されたソースだとgroupListがJavaListになっていないようですが。

    キャンセル

  • 2018/10/29 12:39 編集

    すいませんElementの方を見ていました(汗)。groupListをJavaListにしたところグループの追加はできました。ありがとうございます。追加されたグループを展開しようとすると、index:1 size:1というエラーが出るのですがこれの原因は分かりますでしょうか?

    キャンセル

  • 2018/10/29 12:46 編集

    空のリストでいいので、childListにも追加する必要があります。
    また、childListもJavaListにしてください。

    childList.Add(new JavaList<IDictionary<string, object>>());

    キャンセル

  • 2018/10/31 11:30

    できました!ありがとうございます。あと、親リストの名前が表示されてないのですがこれはなぜでしょう?

    キャンセル

  • 2018/10/31 11:54

    newGroupElementのキーを適当に、GROUPE_LISTにしましたが、実際に使っているGROUPE_TITLEに変えてください

    キャンセル

  • 2018/10/31 12:10

    ありがとうございます。次から次へと申し訳ないのですが、アダプターの更新は行っているのですがリスト追加後に画面遷移すると新しく作ったリストが消えてしまいます。どうしたらよいでしょうか?

    キャンセル

  • 2018/10/31 13:08

    MainActivityが破棄されて、再作成されている状態でしょうか?
    そうであるなら、OnSaveInstanceStateでリストデータを保存しておけばいいです。

    キャンセル

  • 2018/10/31 14:13

    すいません、調べたのですがOnSaveInstanceStateの使いかたがうまくわかりませんでした...

    キャンセル

  • 2018/10/31 16:11

    やり方を追記しました

    キャンセル

  • 2018/11/05 10:33

    ありがとうございます。ですが解決できませんでした。。。
    それと、また別の問題なのですが、データベースを使用していない状態ではアプリ再起動時のリスト保持は難しいでしょうか?

    キャンセル

  • 2018/11/05 12:08 編集

    解決できないとなると、遷移して戻ってきたときに、OnCreateが呼ばれている訳ではないのでしょうか?
    リストの保存に関しては、リストデータをシリアライズしてSharedPreferencesに保存でもなんとかなります。

    キャンセル

  • 2018/11/07 11:20

    調べてみました。なるほど、初期値で再生成されてるということですかね?
    OnResumeを使用すればよいのでしょうか?

    キャンセル

  • 2018/11/07 13:25 編集

    再生成されているのであれば、上記のやり方で大丈夫なはずです。それでダメというならば、再生成されている訳ではないということになるのですが、それであっていますか?
    MainActivityが消えない限り、何もしないでリストが初期化されるとは考えづらいです。
    もしかして、戻るのではなくMainActivityに再度遷移していたりしていませんか?それだと初期化されて当然です。

    キャンセル

  • 2018/11/07 13:38

    おっしゃる通り再遷移していました(汗)。
    すいません、ありがとうございます。お騒がせしました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.48%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • C#

    7413questions

    C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

  • Android

    6628questions

    Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

  • Visual Studio

    1903questions

    Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

  • Xamarin

    518questions

    Xamarin(ザマリン)は、iPhoneなどのiOSやAndroidで動作し、C# 言語を用いてアプリを開発できるクロスプラットフォーム開発環境です。Xamarin Studioと C# 言語を用いて、 iOS と Android の両方の開発を行うことができます。