指定的孩子已经有一个父母。您必须首先在孩子的父母上调用 removeView()。 (C#)

Posted

技术标签:

【中文标题】指定的孩子已经有一个父母。您必须首先在孩子的父母上调用 removeView()。 (C#)【英文标题】:The specified child already has a parent. You must call removeView() on the child's parent first. (C#) 【发布时间】:2016-06-27 10:23:00 【问题描述】:

我已经看到了很多类似的问题,但到目前为止,我所看到的都没有解决我的问题(主要是因为它是在 Java 中,而我使用的是 C#)。

protected override void OnCreate(Bundle bundle)

    base.OnCreate(bundle);
    SetContentView(Resource.Layout.MainV2);

    if (IsThereAnAppToTakePictures())
    
        CreateDirectoryForPictures();
        btnAdd = FindViewById<Button>(Resource.Id.btnAdd);
        btnAdd.Click += DialogAddPhoto;
    

    myFileListAdapter = new ArrayAdapter(this, Resource.Drawable.style_listview);
    listViewFiles = FindViewById<ListView>(Resource.Id.listView1);


private void DialogAddPhoto(object sender, EventArgs eventArgs)

    // passing intent i.e. REQUEST_CAMERA, SELECT_FILE

问题出在哪里...

protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)

    base.OnActivityResult(requestCode, resultCode, data);
    _imageView = new ImageView(this);
    btnRemove = FindViewById<Button>(Resource.Id.btnRemove);

    if (resultCode == Result.Ok)
    
        if (requestCode == REQUEST_CAMERA)
        
            // ................. //
        
        else if ((requestCode == SELECT_FILE) && (data != null))
        
            android.Net.Uri uri = data.Data;
            string imgUri = Convert.ToString(uri);

            string[] proj =  MediaStore.Images.ImageColumns.Data ;
            var cursor = ContentResolver.Query(uri, proj, null, null, null);
            var colIndex = cursor.GetColumnIndex(MediaStore.Images.ImageColumns.Data);
            cursor.MoveToFirst();
            BitmapFactory.Options options = new BitmapFactory.Options  InJustDecodeBounds = true ;
            BitmapFactory.DecodeFile(cursor.GetString(colIndex), options);
            int height = 300;
            int width = Resources.DisplayMetrics.WidthPixels;
            int outHeight = options.OutHeight;
            int outWidth = options.OutWidth;
            int inSampleSize = 1;

            if (outHeight > height || outWidth > width)
                
                    inSampleSize = outWidth > outHeight
                                       ? outHeight / height
                                       : outWidth / width;
                

             options.InSampleSize = inSampleSize;
             options.InJustDecodeBounds = false;
             App.bm = BitmapFactory.DecodeFile(cursor.GetString(colIndex), options);
             System.IO.MemoryStream mem = new System.IO.MemoryStream();
             App.bm.Compress(Bitmap.CompressFormat.Png, 100, mem);
             //byte[] byteArray = mem.ToArray();
             _imageView.SetImageBitmap(App.bm);
             App.bm = null;
             GC.Collect();

             myFileListAdapter.Add(imgUri);
             myFileListAdapter.NotifyDataSetChanged();
             setListViewHeightBasedOnChildren(listViewFiles);

             listViewFiles.ItemClick += (object sender, ItemClickEventArgs e) =>
             
                 AlertDialog.Builder builder = new AlertDialog.Builder(this);
                 builder.SetTitle("Preview");                        
                 builder.SetView(_imageView);
                 builder.SetCancelable(false);
                 builder.SetPositiveButton("Cancel", (senderAlert, args) =>  );
                 builder.SetNegativeButton("Delete?", (senderAlert, args) =>
                 

                     Java.Lang.Object toRemove = myFileListAdapter.GetItem(e.Position);
                     myFileListAdapter.Remove(toRemove);
                     myFileListAdapter.NotifyDataSetChanged();
                     setListViewHeightBasedOnChildren(listViewFiles);

                 );

                 builder.Show();
                ;

            
        
    

这是罪魁祸首。

builder.SetView(_imageView);

我试过这样做,但仍然遇到同样的错误。

builder.SetView(null);
builder.SetView(_imageView);

它的作用是在从图库中选择或添加图像后,Uri 被添加到列表中 (ListView)。单击该项目,将出现一个警报对话框,其中可以看到图像 (_imageView)。单击Cancel 并在图库中的Deleting and Adding 之后查看Uri 图像后发生错误。

我见过的所有解决方案都使用 Inflate,老实说,我不知道如何将它合并到我的代码中,因为 imageview 取决于动态值(从图库中导入的图像)。

请注意,我使用的是 Xamarin Android。

追踪:

06-27 17:51:54.434 E/mono-rt (16678): java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
06-27 17:51:54.434 E/mono-rt (16678):   at android.view.ViewGroup.addViewInner(ViewGroup.java:3430)
06-27 17:51:54.434 E/mono-rt (16678):   at android.view.ViewGroup.addView(ViewGroup.java:3301)
06-27 17:51:54.434 E/mono-rt (16678):   at android.view.ViewGroup.addView(ViewGroup.java:3277)
06-27 17:51:54.434 E/mono-rt (16678):   at com.android.internal.app.AlertController.setupView(AlertController.java:416)
06-27 17:51:54.434 E/mono-rt (16678):   at com.android.internal.app.AlertController.installContent(AlertController.java:244)
06-27 17:51:54.434 E/mono-rt (16678):   at android.app.AlertDialog.onCreate(AlertDialog.java:337)
06-27 17:51:54.434 E/mono-rt (16678):   at android.app.Dialog.dispatchOnCreate(Dialog.java:355)
06-27 17:51:54.434 E/mono-rt (16678):   at android.app.Dialog.show(Dialog.java:260)
06-27 17:51:54.434 E/mono-rt (16678):   at android.app.AlertDialog$Builder.show(AlertDialog.java:951)
06-27 17:51:54.434 E/mono-rt (16678):   at mono.android.widget.AdapterView_OnItemClickListenerImplementor.n_onItemClick(Native Method)
06-27 17:51:54.434 E/mono-rt (16678):   at mono.android.widget.AdapterView_OnItemClickListenerImplementor.onItemClick(AdapterView_OnItemClickListenerImplementor.java:29)
06-27 17:51:54.434 E/mono-rt (16678):   at android.widget.AdapterView.performItemClick(AdapterView.java:298)
06-27 17:51:54.434 E/mono-rt (16678):   at android.widget.AbsListView.performItemClick(AbsListView.java:1128)
06-27 17:51:54.434 E/mono-rt (16678):   at android.widget.AbsListView$PerformClick.run(AbsListView.java:2815)
06-27 17:51:54.434 E/mono-rt (16678):   at android.widget.AbsListView$1.run(AbsListView.java:3574)
06-27 17:51:54.434 E/mono-rt (16678):   at android.os.Handler.handleCallback(Handler.java:800)
06-27 17:51:54.434 E/mono-rt (16678):   at android.os.Handler.dispatchMessage(Handler.java:100)
06-27 17:51:54.434 E/mono-rt (16678):   at android.os.Looper.loop(Looper.java:194)
06-27 17:51:54.434 E/mono-rt (16678):   at android.app.ActivityThread.main(ActivityThread.java:5371)
06-27 17:51:54.434 E/mono-rt (16678):   at java.lang.reflect.Method.invokeNative(Native Method)
06-27 17:51:54.434 E/mono-rt (16678):   at java.lang.reflect.Method.invoke(Method.java:525)
06-27 17:51:54.434 E/mono-rt (16678):   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:833)
06-27 17:51:54.434 E/mono-rt (16678):   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)
06-27 17:51:54.434 E/mono-rt (16678):   at dalvik.system.NativeStart.main(Native Method)

【问题讨论】:

您能否将堆栈跟踪添加到您的答案中? @YumeYume 我刚刚做了。请检查。 【参考方案1】:

图像视图已经分配给一个父创建一个新的图像视图并设置它

  AlertDialog.Builder builder = new AlertDialog.Builder(this);
                 builder.SetTitle("Preview");  
 var temp= new ImageView(this);   
temp.SetImageBitmap(App.bm);                   
                 builder.SetView(temp);
                 builder.SetCancelable(false);
                 builder.SetPositiveButton("Cancel", (senderAlert, args) =>  );
                 builder.SetNegativeButton("Delete?", (senderAlert, args) =>
                 

                     Java.Lang.Object toRemove = myFileListAdapter.GetItem(e.Position);
                     myFileListAdapter.Remove(toRemove);
                     myFileListAdapter.NotifyDataSetChanged();
                     setListViewHeightBasedOnChildren(listViewFiles);

                 );

                 builder.Show();
                ;

【讨论】:

这似乎有效,我不再收到错误但添加另一个图像后,查看图像的对话框正在重复。例如,我添加了一张照片,然后我查看了它,删除它后,我添加了另一张照片。当我查看它然后单击取消时,之前添加的图像的对话框就在那里。这让我很困惑。 还有一个是我添加了很多照片,当我一张一张点击时,对话框中只有最新添加的照片。 请使用 -= 取消绑定事件处理程序,方法与使用 += 添加的方式相同,并在删除时关闭对话框 抱歉回复晚了。我应该取消绑定什么事件处理程序?像这样:listViewFiles.ItemClick -= (object sender, ItemClickEventArgs e)?似乎也没有选择解雇AlertDialog.Builder?我是新手,所以希望你不要介意。 listViewFiles.ItemClick += ClickHandler;.... ClickHandler(object sender, ItemClickEventArgs e)... listViewFiles.ItemClick -= ClickHandler【参考方案2】:

TLDR;

我在 WPF 中遇到了类似的问题。我如何解决它的步骤(代码用于 WPF,API 在 XAMARIN 中可能不同):

    获取我需要的孩子的参考。 Grid contentGrid = page.ContentGrid; 从父级中移除子级(有点悲伤)。在我的情况下,父级是一个名为 MainGrid: page.MainGrid.Children.Remove(contentGrid); 的网格

看起来,在你的情况下,Children 集合 si 的 Remove() 方法称为 RemoveView(),因为它们将控件称为“视图”,我个人讨厌。

【讨论】:

老实说,我不知道从哪里获得参考以及我应该使用什么 Parent。是ImageView 还是AlertDialog

以上是关于指定的孩子已经有一个父母。您必须首先在孩子的父母上调用 removeView()。 (C#)的主要内容,如果未能解决你的问题,请参考以下文章

我继续收到错误消息“指定的孩子已经有一个父母。您必须首先在该孩子的父母上调用removeView()(Android)

冲突的 Android 错误消息:指定的孩子已经有一个父母。您必须先在孩子的父母上调用 removeView()

指定的孩子已经有一个父母。您必须先在孩子的父母上调用 removeView()

Fragments - 指定的孩子已经有一个父母。您必须先在孩子的父母上调用 removeView()

收到错误“指定的孩子已经有父母。您必须先在孩子的父母上调用 removeView()。”? [复制]

Android - ArrayAdapter<LinearLayout> :指定的孩子已经有一个父母。您必须先在孩子的父母上调用 removeView()