CarouselPage, дочерние элементы.Add генерирует исключение ‘Значение не может быть нулевым. Имя параметра: ключ’

#xamarin #exception #null #carousel #children

#xamarin #исключение #null #карусель #дочерние элементы

Вопрос:

Я разрабатываю Xamarin.Приложение для Android, главная страница которого представляет собой страницу карусели с 3 дочерними элементами (3 изображения, которые на самом деле существуют на диске).

Вот код XAML страницы:

 <?xml version="1.0" encoding="utf-8" ?>
<CarouselPage xmlns="http://xamarin.com/schemas/2014/forms" 
          xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
          x:Class="MyApp.StartPage"
          x:Name="CarouselStartPage">
</CarouselPage>
  

Ниже в коде главной страницы я добавляю 3 изображения в карусель:

В начале моего приложения я загружаю изображения на страницу карусели, используя следующий код:

 string[] imgPaths = GetImages();
for (string imgPath in imgPaths)
{
   // Image creation with a tapgesturerecognizer.
   TapGestureRecognizer tapGestureRecognizer = new TapGestureRecognizer();
   tapGestureRecognizer.SetBinding(TapGestureRecognizer.CommandProperty, "StartCmd");
   
   Image img = new Image()
   {
      Source = imgPath,
   };
   img.GestureRecognizers.Add(tapGestureRecognizer);

   Device.BeginInvokeOnMainThread()
   {

       this.Children.Add(new ContentPage()
       {
            Content = new StackLayout()
            {
                 Children =
                 {
                   img,
                 },
            },
       });
   }
}
  

Но строка эта.Children.Add(…) иногда (не всегда) генерирует следующее исключение:

 Value cannot be null.
                        // Parameter name: key AT   at System.Collections.Generic.Dictionary`2[TKey, TValue].FindEntry(TKey key)[0x00008] in < 5a13d71824a44a4fb1cc4a6f176c0719 >:0
                        //   at System.Collections.Generic.Dictionary`2[TKey, TValue].ContainsKey(TKey key)[0x00000] in < 5a13d71824a44a4fb1cc4a6f176c0719 >:0
                        //   at Xamarin.Forms.ResourcesExtensions.GetMergedResources(Xamarin.Forms.IElement element)[0x00063] in < 59b03de64f0e485e8c9d8ead0b747e17 >:0
                        //   at Xamarin.Forms.Element.set_Parent(Xamarin.Forms.Element value)[0x0004a] in < 59b03de64f0e485e8c9d8ead0b747e17 >:0
                        //   at Xamarin.Forms.Element.OnChildAdded(Xamarin.Forms.Element child)[0x00000] in < 59b03de64f0e485e8c9d8ead0b747e17 >:0
                        //   at Xamarin.Forms.VisualElement.OnChildAdded(Xamarin.Forms.Element child)[0x00000] in < 59b03de64f0e485e8c9d8ead0b747e17 >:0
                        //   at Xamarin.Forms.MultiPage`1[T].OnChildAdded(Xamarin.Forms.Element child)[0x00000] in < 59b03de64f0e485e8c9d8ead0b747e17 >:0
                        //   at Xamarin.Forms.Page.OnInternalAdded(Xamarin.Forms.VisualElement view)[0x00013] in < 59b03de64f0e485e8c9d8ead0b747e17 >:0
                        //   at Xamarin.Forms.Page.InternalChildrenOnCollectionChanged(System.Object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)[0x0005f] in < 59b03de64f0e485e8c9d8ead0b747e17 >:0
                        //   at(wrapper delegate- invoke) < Module >.invoke_void_object_NotifyCollectionChangedEventArgs(object, System.Collections.Specialized.NotifyCollectionChangedEventArgs)
                        //   at System.Collections.ObjectModel.ObservableCollection`1[T].OnCollectionChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs e)[0x00018] in < 4335f7a6733349bfa94d12b891eed9c1 >:0
                        //   at System.Collections.ObjectModel.ObservableCollection`1[T].OnCollectionChanged(System.Collections.Specialized.NotifyCollectionChangedAction action, System.Object item, System.Int32 index)[0x00009] in < 4335f7a6733349bfa94d12b891eed9c1 >:0
                        //   at System.Collections.ObjectModel.ObservableCollection`1[T].InsertItem(System.Int32 index, T item)[0x0001a] in < 4335f7a6733349bfa94d12b891eed9c1 >:0
                        //   at System.Collections.ObjectModel.Collection`1[T].Add(T item)[0x00020] in < 5a13d71824a44a4fb1cc4a6f176c0719 >:0
                        //   at Xamarin.Forms.ObservableWrapper`2[TTrack, TRestrict].Add(TRestrict item)[0x0004b] in < 59b03de64f0e485e8c9d8ead0b747e17 >:0
                        //   at BorneLs.Core.Views.StartPage  <> c__DisplayClass11_0.< RefreshWelcomeUi > b__0()[0x00097] in < dd6514dc2c5c4d5da8fd19a9afc9d43a >:0
                        //   at Java.Lang.Thread   RunnableImplementor.Run()[0x00008] in < fcb13297ceea443792cf4dd4e406ba23 >:0
                        //   at Java.Lang.IRunnableInvoker.n_Run(System.IntPtr jnienv, System.IntPtr native__this)[0x00009] in < fcb13297ceea443792cf4dd4e406ba23 >:0
                        //   at(wrapper dynamic - method) System.Object.17(intptr, intptr))'
  

Но я не понимаю почему, потому что я тестировал добавление изображения, которого нет на диске, и я не добавляю такое исключение?

Может кто-нибудь помочь мне выяснить, что происходит и почему я иногда получаю эту ошибку? Спасибо за любую помощь

РЕДАКТИРОВАТЬ: Дополнительная информация Я только что обнаружил, что данное исключение было вызвано следующим: ИСКЛЮЧЕНИЕ: PagerAdapter приложения изменил содержимое адаптера без вызова PagerAdapter#notifyDataSetChanged! , поэтому, возможно, мне придется переключиться с carouselpage на carouselview.

Комментарии:

1. CarouselPage устарел в пользу CarouselView

2. Спасибо за комментарий, я попробую carouselview, я только что обнаружил, что данное исключение было вызвано следующим: ИСКЛЮЧЕНИЕ: PagerAdapter приложения изменил содержимое адаптера без вызова PagerAdapter#notifyDataSetChanged! , так что, возможно, мне придется переключиться с carouselpage на carouselview.

3. Я протестировал ваш код в базовой демонстрации, он работает нормально. Возможно, что-то не так с for и устройством. Команда BeginInvokeOnMainThread . Попробуйте следующий код : public CustomCarouselPage() { InitializeComponent(); string[] imgPaths = GetImages(); foreach (var imgPath in imgPaths) { ... Image img = new Image() { Source = imgPath, }; Device.BeginInvokeOnMainThread(() => { this.Children.Add(new ContentPage() { ... }); }); } } .

4. Большое вам спасибо @Jarvan Zhang за вашу идею, но я не вижу разницы между написанным мной кодом и вашим предложением. Вы имели в виду, что я должен попытаться внедрить «цикл for» внутри устройства. BeginInvokeOnMainThread?

5. for (string imgPath in imgPaths){} Код должен быть foreach (string imgPath in imgPaths){} . И, похоже, вы не добавили действие в метод BeginInvokeOnMainThread, например Device.BeginInvokeOnMainThread(()=>{}); . Когда я тестирую код, возникли ошибки компиляции.

Ответ №1:

Я окончательно попытаюсь заменить устаревшую страницу CarouselView на CarouselView, чтобы увидеть, не может ли значение исключения быть нулевым. Ключ параметра» исчезает, потому что действительно странно, что он иногда возникает (я бы сказал, 1% времени) без причины. Я дам вам знать и опубликую свой код впоследствии, чтобы у людей, столкнувшихся с этим исключением, было решение.

Спасибо