2017-10-19 104 views
0

我想向我的Xamarin表單中添加一個Picker,該表單顯示模板名稱列表,並允許用戶選擇一個。如何在Xamarin Picker中調試綁定問題

這裏是以下形式:

<?xml version="1.0" encoding="utf-8" ?> 
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" 
      xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
      xmlns:local="clr-namespace:DefectReport" 
      x:Class="DefectReport.VehiclePage"> 
    <ContentPage.Content> 
     <ScrollView> 
      <StackLayout> 
       <Label x:Name="Message" TextColor="Red" /> 
       <Label Text="Registration Number" /> 
       <Entry Text="{Binding Vehicle.RegistrationNumber}" /> 
       <Label Text="Description" /> 
       <Entry Text="{Binding Vehicle.Description}" /> 
       <Entry Text="Vehicle Type" /> 
       <Picker ItemsSource="{Binding Templates, PresentationTraceSources.TraceLevel=High}" ItemDisplayBinding="{Binding TemplateName}" SelectedItem="{Binding SelectedTemplate}"/> 
       <Button Text="Save" Clicked="SaveButton_Clicked" /> 
      </StackLayout> 
     </ScrollView> 
    </ContentPage.Content> 
</ContentPage> 

這裏是後面的代碼:

[XamlCompilation(XamlCompilationOptions.Compile)] 
public partial class VehiclePage : ContentPage { 
    Vehicle Vehicle { get; set; } 
    ObservableCollection<Template> Templates { get; set; } 
    Template SelectedTemplate { get; set; } 

    public VehiclePage(Vehicle vehicle, List<Template> templates) { 
     Vehicle = vehicle ?? new Vehicle(); 
     Templates = new ObservableCollection<Template>(templates); 
     SelectedTemplate = templates.FirstOrDefault(t => t.ServerRecordId == Vehicle.TemplateId) ?? templates.FirstOrDefault(); 
     BindingContext = this; 
     InitializeComponent(); 
    } 

    private async void SaveButton_Clicked(object sender, EventArgs e) { 

    } 
} 

模板和車輛類別:

public class Template { 
    [PrimaryKey] 
    [AutoIncrement] 
    public int DeviceRecordId { get; set; } 
    [Indexed] 
    public int idTemplate { get; set; } 
    public string TemplateName { get; set; } 
    public string TemplateData { get; set; } 
    [Ignore] 
    public int ServerRecordId { 
     get { 
      return idTemplate; 
     } 
     set { 
      idTemplate = value; 
     } 
    } 
} 

public class Vehicle { 
    [PrimaryKey] 
    [AutoIncrement] 
    public int DeviceRecordId { get; set; } 
    [Indexed] 
    public int idVehicle { get; set; } 
    [Indexed] 
    public string RegistrationNumber { get; set; } 
    public string Description { get; set; } 
    public int TemplateId { get; set; } 
    [Ignore] 
    public ServerRecordId { 
     get { 
      return idVehicle; 
     } 
     set { 
      idVehicle = value; 
     } 
    } 
} 

當我顯示形式,供給列表的1個模板中,下拉列表中沒有模板。

另外,當我向表單輸入數據時,在SaveButton_Clicked方法中,即使輸入了一些數據,Vehicle.RegistrationNumber和Vehicle.Description也沒有填充。

我看不到如何調試 - 這一切都隱藏起來!

+0

你只能綁定到屬性 - 模板不是屬性 – Jason

+0

要調試綁定,通常:'ControlProperty =「{綁定MyVMProp,PresentationTraceSources.TraceLevel = High}'。在調試器的運行時,您會在VS Output窗格中看到大量的調試信息。 –

+0

我現在已將可綁定項目更改爲屬性(我已更改問題中的代碼)。我添加了PresentationTraceSources.TraceLevel = High,但它停止窗體編譯「錯誤:值不能爲空。錯誤:參數名稱:clrNamespace「 –

回答

1

一些建議,可以不是解決辦法:

    當您使用「綁定」
  1. 你應該使用的ObservableCollection而不是List
  2. 你的屬性應該執行INotifyPropertyChanged
  3. 您應該使用get和設置爲

    車輛{get; set;}

    列表模板{get; set;}

+0

感謝您的建議。 1和3(沒有區別)。至於2,在設置BindingContext之後,沒有任何屬性發生變化 - 是否真的有必要(這是需要添加到每個屬性的很多代碼)? –

+0

我實現了一個單獨的類來保存數據(即沒有使用表單本身作爲BindingContext),它都開始工作,不知道這是爲什麼。 –

0

基於亞歷山德羅Caliaro的答案,用加法:

我做了一個單獨的類的數據 - 使用thisBindingContext不起作用,因爲某些原因。我讓課程實現了INotifyPropertyChanged

我將列表更改爲ObservableCollection

我提出的所有數據進性能,具有通知,從而:

public class VehicleInfo : Model { 
     private Vehicle selectedVehicle; 

     public Vehicle SelectedVehicle { 
      get { return selectedVehicle; } 
      set { 
       if (selectedVehicle != value) { 
        selectedVehicle = value; 
        OnPropertyChanged("SelectedVehicle"); 
       } 
      } 
     } 

     private ObservableCollection<Vehicle> vehicles; 

     public ObservableCollection<Vehicle> Vehicles { 
      get { return vehicles; } 
      set { 
       if (vehicles != value) { 
        vehicles = value; 
        OnPropertyChanged("Vehicles"); 
       } 
      } 
     } 


     private Template selectedTemplate; 

     public Template SelectedTemplate { 
      get { return selectedTemplate; } 
      set { 
       if (selectedTemplate != value) { 
        selectedTemplate = value; 
        OnPropertyChanged("SelectedTemplate"); 
       } 
      } 
     } 

    } 

模型是一個簡單的類,它實現INotifyPropertyChanged

public class Model : System.ComponentModel.INotifyPropertyChanged { 
    public void OnPropertyChanged(string name) { 
     if (PropertyChanged != null) 
      PropertyChanged(this, new PropertyChangedEventArgs(name)); 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 
} 

爲了保存所有的繁瑣的打字,我添加一個代碼片段到Visual Studio 2017做屬性:

<?xml version="1.0" encoding="utf-8" ?> 
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet"> 
    <CodeSnippet Format="1.0.0"> 
     <Header> 
      <Title>propn</Title> 
      <Shortcut>propn</Shortcut> 
      <Description>Code snippet for property and backing field with notification</Description> 
      <Author>Nikki Locke</Author> 
      <SnippetTypes> 
       <SnippetType>Expansion</SnippetType> 
      </SnippetTypes> 
     </Header> 
     <Snippet> 
      <Declarations> 
       <Literal> 
        <ID>type</ID> 
        <ToolTip>Property type</ToolTip> 
        <Default>int</Default> 
       </Literal> 
       <Literal> 
        <ID>property</ID> 
        <ToolTip>Property name</ToolTip> 
        <Default>MyProperty</Default> 
       </Literal> 
       <Literal> 
        <ID>field</ID> 
        <ToolTip>The variable backing this property</ToolTip> 
        <Default>myVar</Default> 
       </Literal> 
      </Declarations> 
      <Code Language="csharp"><![CDATA[private $type$ $field$; 

    public $type$ $property$ 
    { 
     get { return $field$;} 
     set { 
      if($field$ != value) { 
       $field$ = value; 
       OnPropertyChanged("$property$"); 
      } 
     } 
    } 
    $end$]]> 
      </Code> 
     </Snippet> 
    </CodeSnippet> 
</CodeSnippets>