如何调试 Xamarin Picker 中的绑定问题
How to debug binding problems in Xamarin Picker
我想在我的 Xamarin 表单中添加一个选择器,它显示模板名称列表,并允许用户选择一个。
表格如下:
<?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没有填写,即使我输入了一些数据。
我看不出如何调试它 - 一切都被隐藏起来了!
一些不能解决的建议:
- 当您使用 "Bindings" 时,您应该使用 ObservableCollection 而不是 List
- 您的属性应实现 INotifyPropertyChanged
你应该使用get和set
车辆车辆{get;set;}
列表模板{get;set;}
根据亚历山德罗·卡利亚罗的回答,添加:
我为数据创建了一个单独的 class - 使用 this
因为 BindingContext
出于某种原因不起作用。我制作了 class 工具 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");
}
}
}
}
模型是一个简单的 class,实现了 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 Studio2017中添加了一段代码来做属性:
<?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>
我想在我的 Xamarin 表单中添加一个选择器,它显示模板名称列表,并允许用户选择一个。
表格如下:
<?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没有填写,即使我输入了一些数据。
我看不出如何调试它 - 一切都被隐藏起来了!
一些不能解决的建议:
- 当您使用 "Bindings" 时,您应该使用 ObservableCollection 而不是 List
- 您的属性应实现 INotifyPropertyChanged
你应该使用get和set
车辆车辆{get;set;}
列表模板{get;set;}
根据亚历山德罗·卡利亚罗的回答,添加:
我为数据创建了一个单独的 class - 使用 this
因为 BindingContext
出于某种原因不起作用。我制作了 class 工具 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");
}
}
}
}
模型是一个简单的 class,实现了 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 Studio2017中添加了一段代码来做属性:
<?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>