2017-10-19 68 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>