2016-11-23 81 views
0

大家早上好,我看了几个我研究过的地方,但没有找到解决方案来解决我的问题。 我是C#,XAML和Xamarin的新手,我正在做一个应用程序,在屏幕上创建产品列表,产品屏幕已通过Json WebApi填充。直到那里everthing看起来不错,但因为我试图添加“添加”和“共享”功能,它正在加载主页面并在导航到listsPage时崩溃。 我需要从产品页面获取产品并将其添加到我的清单所在的另一个视图中。我用'Share'和'AddToList'创建了一个ContextActions,但我不知道如何获得该产品,并将它添加到我的列表中。与'共享'相同的问题,当我得到MenuItem,并尝试将其传递给我的ProductViewModel中的任务我得到一个NullReferenceException,但对象不是null。 我很感激有人能帮我解决这个问题。 我知道这个帖子已经很长了,但我想给每一个可能的信息。Xamarin.Forms添加和共享项目CrashApp

这里是我的列表页:

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

ListsModel:

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

ListProductModel:

SearchProductPage:

<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; 
    } 
} 
+0

你能分享你的解决方案吗? Dropbox的? –

+0

当然。对不起,不要提前发布。 https://www.dropbox.com/sh/7xcouu90vo69cms/AABGXgGlrSxw22KJfTMRQArWa?dl=0 –

+0

所以,我能够构建它并在Android上运行。我看到2个标签页,但它不是英文的。我应该按什么来查看问题?我可以点击“AGORA Nao”,然后点击“+”标志并添加产品到“MINHAS LISTAS” –

回答

1

这里是你的出发点。其余的你可以使用相同的模式在构造函数中传递你的新产品,或者只是在视图模型中实现setter。

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

+0

感谢您的帮助。我会稍后再尝试并检查结果,但再次感谢您花费一些时间来帮助我。 –