0

大家早上好,我查看了我研究过的几个地方,但没有找到适合我的问题的解决方案。我是 C#、XAML 和 Xamarin 的新手,我正在做一个应用程序,它在屏幕上创建带有产品的列表,带有产品的屏幕是通过 Json WebApi 填充的。直到一切看起来都很好,但是由于我尝试添加“添加”和“共享”功能,它正在加载主页并在导航到列表页时崩溃。我需要从产品页面获取产品并将其添加到我的列表所在的另一个视图中。我使用“Share”和“AddToList”创建了一个 ContextActions,但我不知道如何获取该产品并将其“添加”到我的列表中。当我获取 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>

和我的listDetail:

    <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>

搜索页面代码隐藏:

 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;
    }
}
4

1 回答 1

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 并将其存储在您的数据库中,或者通过构造函数或一些设置器进一步传递给其他模型或视图。

于 2016-11-24T23:19:12.100 回答