Xamarin.Forms Добавить элемент и поделиться им CrashApp

Доброе утро всем, я просмотрел несколько мест, которые я исследовал, и не нашел решения, которое сработало для моих проблем. Я новичок в C #, XAML и Xamarin, я делаю приложение, которое создает списки с продуктами на экране, экран с продуктами заполняется через Json WebApi. Пока все выглядит нормально, но поскольку я пытался добавить функции «ДОБАВИТЬ» и «Поделиться», он загружает главную страницу и вылетает при переходе к listsPage. Мне нужно получить продукт со страницы продукта и добавить его в другое представление, где находятся мои списки. Я создал ContextActions с «Share» и «AddToList», но я не знаю, как получить этот продукт и «добавить» его в свои списки. Та же проблема с «Поделиться», когда я получаю MenuItem и пытаюсь передать его задаче в моей ProductViewModel, я получаю исключение NullReferenceException, но объект не является нулевым. Я ценю, если кто-то может помочь мне с этой проблемой. Я знаю, что пост получился довольно длинным, но я хотел дать всю возможную информацию.

Вот моя страница списков:

<ListView x:Name="listaView" ItemSelected="listSelected" >
    <ListView.ItemTemplate>
      <DataTemplate>
       <ViewCell>
        <ViewCell.View>
          <StackLayout Padding="20,0,20,0"
                       Orientation="Horizontal"
                       HorizontalOptions="FillAndExpand">

            <Label Text="{Binding Name}"
                   VerticalTextAlignment="Center"
                   HorizontalOptions="StartAndExpand" />

            <Image Source="check.png"
                   HorizontalOptions="Start"
                   IsVisible="{Binding Done}" />
            </StackLayout>
        </ViewCell.View>
       </ViewCell>
      </DataTemplate>
    </ListView.ItemTemplate>
  </ListView>
</ContentPage>

и мой списокДетали:

    <Label Text="Name" />
    <Entry x:Name="nameEntry" Text="{Binding Name}" />
    <Label Text="Description" />
    <Entry x:Name="descriptionEntry" Text="{Binding Description}" />
    <Label Text="Typ" />
    <controls:BindablePicker x:TypeArguments="enums:Typ" SelectedItem="{Binding Typ}" />
    <Label Text="Done" />
    <Switch x:Name="doneEntry" IsToggled="{Binding Done}" />
    <Label Text="Products:" />
    <ListView ItemsSource="{Binding Products}" >
      <ListView.ItemTemplate>
        <DataTemplate>
          <ViewCell>
            <ViewCell.View>
              <StackLayout Orientation="Horizontal">
                <Image Aspect="AspectFit" HeightRequest="20" WidthRequest="20" Source="{Binding Image}" />
                <Label Text="{Binding Name}"  />
                <Label Text="{Binding Price, StringFormat='R${0:C2}'}" />
              </StackLayout>
            </ViewCell.View>
          </ViewCell>
        </DataTemplate>
      </ListView.ItemTemplate>
    </ListView>

    <Button Text="Save" Clicked="salveClicked" />
    <Button Text="Delete" Clicked="deleteClicked" />
    <Button Text="Cancel" Clicked="cancelClicked" />
    <Button Text="Speak" Clicked="speakClicked" />

  </StackLayout>
</ContentPage>

ListDetails КОД:

public ProductListDetailPage()
        {
            InitializeComponent();

            NavigationPage.SetHasNavigationBar(this, true);

                   }

        void saveClicked(object sender, EventArgs e)
        {
            var lista = (Lists)BindingContext;
            App.Database.SaveList(lista);
            this.Navigation.PopAsync();
        }

        void deleteClicked(object sender, EventArgs e)
        {
            var lista = (Lists)BindingContext;
            App.Database.DeleteList(lista.ListaID);
            this.Navigation.PopAsync();
        }

        void cancelClicked(object sender, EventArgs e)
        {
            var lista = (Lists)BindingContext;
            this.Navigation.PopAsync();
        }

        void speakClicked(object sender, EventArgs e)
        {
            var lists = (Lists)BindingContext;
            DependencyService.Get<ITextToSpeech>().Speak(lists.Name+ " " + lists.Descrip);
        }
    }
}

Я считаю, что проблема в моей модели, но понятия не имею, что это такое

Модель продукта:

public class Product : INotifyPropertyChanged
    {
        private int id;
        public int ProductID
        {
            get { return id; }
            set
            {
                id = value;
                this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(id)));
            }
        }

        private string name;
        public string Name
        {
            get { return name; }
            set
            {
                name= value;
                this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(name)));
            }
        }

        private double price;
        public double Price{
            get { return price; }
            set
            {
                price= value;
                this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(price)));
            }
        }

        private string dtFab;
        public string DtFab
        {
            get { return dtFab; }
            set
            {
                dtFab= value;
                this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(dtFab)));
            }
        }

        private string dtValid;
        public string DtValid        {
            get { return dtValid; }
            set
            {
                dtValid= value;
                this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(dtValid)));
            }
        }

        private string amount;
        public string Amount{
            get { return quantidade; }
            set
            {
                amount= value;
                this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(amount)));
            }
        }

        private string descrip;
        public string Descrip{
            get { return descrip; }
            set
            {
                descrip= value;
                this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(descrip)));
            }
        }

        private string image;
        public string Image
        {
            get { return image; }
            set
            {
                image= value;
                this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(image)));
            }
        }

        private ICollection<ListProduct> listProduct;
        public ICollection<ListProduct> ListProduct{
            get { return listProduct; }
            set
            {
                listProduct= value;
                this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(listProduct)));
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
    }
}

СпискиМодель:

public class Lists
    {

        public Lista()
        {
        }

        [PrimaryKey, AutoIncrement]
        public int ListID get; set; }
        public string Name { get; set; }
        public string Descrip { get; set; }
        public bool Done { get; set; }
        public Typ Typ { get; set; }



        public virtual ICollection<ListsProduct> ListsProducts{ get; set; }

}
public class ListsProduct
{
        public int ListsProductID{ get; set; }
        public int ListID { get; set; }
        public int ProductID { get; set; }
        public virtual Lists Lists { get; set; }
        public virtual Product Product { get; set; }
    }
}

СписокМодельПродукта:

Страница продукта:

<StackLayout Orientation="Vertical">

    <SearchBar Text="{Binding SearchBarText}" />
    <Button x:Name="btnPesquisar" Text="Search" Command="{Binding SearchCommand}" />
    <ListView ItemsSource="{Binding Products}">
      <ListView.ItemTemplate>
        <DataTemplate>
          <ViewCell>
            <ViewCell.ContextActions>
              <MenuItem Text="Share" Clicked="ShareProduct" />
              <MenuItem Text="Add To" Clicked="AddProduct" />
            </ViewCell.ContextActions>
            <ViewCell.View>
              <StackLayout Orientation="Horizontal" HorizontalOptions="FillAndExpand" >
                <Image Aspect="AspectFit" HeightRequest="20" WidthRequest="20" Source="{Binding Image}" />
                <Label Text="{Binding Name}"  />
                <Label Text="{Binding Price, StringFormat='R${0:C2}'}" HorizontalOptions="End" />
              </StackLayout>
            </ViewCell.View>
          </ViewCell>
        </DataTemplate>
      </ListView.ItemTemplate>
    </ListView>
  </StackLayout>
</ContentPage>

Код SearchPage:

 public partial class SearchPage: ContentPage
    {
        ProductsViewModel viewModel;
        public TelaPesquisaView()
        {
            InitializeComponent();

            this.BindingContext = new ViewModels.ProductsViewModel();
        }


        public async void AddProduct(object sender, EventArgs e)
        {
            var al = ((MenuItem)sender);
            await viewModel.AddToList(al.BindingContext as Product);
            var produtoLista = new ListsPage();
            await Navigation.PushAsync(produtoLista);
        }

        public async void ShareProduct(object sender, EventArgs e)
        {
            var al = ((MenuItem)sender);
            if (al != null) { 
            await viewModel.Share(al.BindingContext as Produto);
            }
        }
    }
}

И ProductViewModel

public class ProductViewModel : INotifyPropertyChanged
    {
        private string searchBarText = string.Empty;
        public string SearchBarText {
            get { return searchBarText ; }
            set
            {
                if (searchBarText != value)
                {
                    searchBarText = value ?? string.Empty;
                    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(searchBarText )));

                    if (SearchCommand.CanExecute(null))
                    {
                        SearchCommand.Execute(null);
                    }
                }
            }
        }

        // filtrar somente os 5 primeiros

        #region Command SearchCommand
        private Xamarin.Forms.Command searchCommand;
        public ICommand SearchCommand{
            get
            {
                searchCommand= searchCommand?? new Xamarin.Forms.Command(DoSearchCommand, ExecuteCommand);
                return searchCommand;
            }
            set
            {
                searchCommand= (Xamarin.Forms.Command)value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(searchCommand)));
            }
        }
        private void DoSearchCommand()
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Products)));
        }
        private bool ExecuteCommand()
        {
            return true;
        }
        #endregion
        private ObservableCollection<Models.Produto> products; 
        public ObservableCollection<Models.Produto> Products             {
            get
            {
                ObservableCollection<Models.Product> searchProducts = new ObservableCollection<Models.Product>();

                if (products != null)
                {

                    List<Models.Product> prod = (from p in products
                                                 where p.Name.ToLower().Contains(searchBarText.ToLower())select p).Take(3).ToList<Models.Product>();

                    if (prod != null && prod.Any())
                    {
                        searchedProducts = new ObservableCollection<Models.Product>(prod);
                    }
                }
                return searchedProducts ;
            }  
            set
            {
                products = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Products)));
            }
        } 

        public ProductsViewModel()
        {
            SearchCommand = new Xamarin.Forms.Command(async () =>
            {
                var products = await ApiProducts.Api.GetAsync();
                Products = new ObservableCollection<Models.Product>(products );
            });


        }

        public async Task AddToList(ListsProduct prod)
        {

            Lists list = new Lists();
            list.ListsProduct.Add(prod);
            App.Database.SaveList(list);


        }
        public async Task Share(Models.Product prod)
        {
            var title = prod.NomeProduto;
            var message = prod.ToString();


            // Share message and an optional title.
            await CrossShare.Current.Share(message, title );


        }

        public event PropertyChangedEventHandler PropertyChanged;
    }
}

person Victor Gabriel Bucar Freitas    schedule 23.11.2016    source источник
comment
Вы можете просто поделиться своим решением где-нибудь? ящик?   -  person Yuri S    schedule 23.11.2016
comment
Конечно. Извините, что не выложил раньше. dropbox.com/sh/7xcouu90vo69cms/AABGXgGlrSxw22KJfTMRQArWa?dl=0   -  person Victor Gabriel Bucar Freitas    schedule 24.11.2016
comment
Итак, я смог собрать его и запустить на Android. Я вижу страницу с двумя вкладками, но она не на английском языке. Что нужно нажать, чтобы увидеть проблему? Я смог щелкнуть AGORA Nao, затем подписать + и добавить продукт в MINHAS LISTAS.   -  person Yuri S    schedule 24.11.2016
comment
Мне жаль, что мой проект на португальском языке, и у меня не было времени, чтобы перевести его. Вы должны щелкнуть вкладку Pesquisa (Поиск), если вы нажмете кнопку Pesquisar (Поиск), я загружу некоторые продукты и при долгом нажатии продукт плохо загружает меню с 2 вариантами. То, чего я пытаюсь добиться, - это когда вы нажимаете Adicionar à (Добавить в), получаете нажатый элемент и добавляете его в список в Minhas Listas (Мои списки).   -  person Victor Gabriel Bucar Freitas    schedule 24.11.2016
comment
Есть еще одна вещь, по какой-то причине Android не может получить доступ к данным, если вы используете uwp, он отлично загрузит данные о продуктах.   -  person Victor Gabriel Bucar Freitas    schedule 24.11.2016
comment
Я вижу, что httpclient указывает на localhost. Будет ли он использоваться в вашем сценарии?   -  person Yuri S    schedule 24.11.2016
comment
Это плохо, но только для целей тестирования я не смог найти способ запустить его на Android с помощью localhost. Есть ли лучший способ сделать это?   -  person Victor Gabriel Bucar Freitas    schedule 24.11.2016
comment
Вы должны использовать IP-адрес для вашего ПК, на котором работает служба, если они находятся в одной сети. Также вы не можете разместить свой сервис в Express, в этом случае используйте локальный IIS.   -  person Yuri S    schedule 24.11.2016


Ответы (1)


Вот отправная точка для вас. В остальном вы можете использовать тот же шаблон, передавая новый продукт в конструкторы, или просто реализовать сеттеры в своих моделях представления.

  1. Определить привязку для получения нового продукта

    <MenuItem Text="Adicionar à" Clicked="AdicionaProduto" CommandParameter="{Binding .}" />
    
  2. Затем передайте его конструктору ListasView в качестве параметра.

    public async void AdicionaProduto(object sender, EventArgs e)
        {
            var al = ((MenuItem)sender);
            var produtoLista = new ListasView(al.CommandParameter as Produto);
            await Navigation.PushAsync(produtoLista);
        }
    
  3. Чтобы сделать это, вам нужно изменить конструктор

    public ListasView(Produto newProduto = null)
    {
        InitializeComponent();
        //this.BindingContext = new ViewModels.ListasViewModel();
    
        if (newProduto != null)
        {
            //do something
            int x = 0;
        }
    

Вы можете взять этот newProduto и сохранить его в своей БД или перейти к другим моделям или представлениям через конструктор или некоторые сеттеры.

person Yuri S    schedule 24.11.2016
comment
Спасибо за помощь. я попробую позже и проверю результат, но еще раз спасибо, что нашли время, чтобы помочь мне. - person Victor Gabriel Bucar Freitas; 25.11.2016