如何将数据绑定到 xamarin 表单中的可绑定属性
How to bind data to the bindableproperty in xamarin forms
我有两个使用相同表单的页面,因此我创建了表单的内容视图并应用了如下可绑定属性:
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ListContact.Extension.EditForm">
<StackLayout Padding="20">
<Label Text="Edit Contact Forms"
HorizontalOptions="Center"
FontSize="20"
TextColor="Blue"
VerticalOptions="Start"/>
<Label Text="Name"/>
<Entry x:Name="txtName" Text="{Binding NameText}" Placeholder="Name"/>
<Label Text="Phone number"/>
<Entry x:Name="txtPhoneNumber" Text="{Binding PhoneNumberText}" Placeholder="Phone number" Keyboard="Telephone"/>
<Label Text="Email"/>
<Entry x:Name="txtEmail" Text="{Binding EmailText}" Placeholder="Email" Keyboard="Email"/>
<Label Text="Description"/>
<Editor x:Name="txtDescription" Text="{Binding DescriptionText}" Placeholder="Description"
HeightRequest="70"/>
</StackLayout>
</ContentView>
这是背后的代码:
using ListContact.ViewModel;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace ListContact.Extension
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class EditForm : ContentView
{
private static readonly BindableProperty NameProperty = BindableProperty.Create("NameText", typeof(object), typeof(EditForm));
public string NameText { get => (string)GetValue(NameProperty); set => SetValue(NameProperty, value); }
private static readonly BindableProperty PhoneProperty = BindableProperty.Create("PhoneNumberText", typeof(string), typeof(EditForm));
public string PhoneNumberText { get => (string)GetValue(PhoneProperty); set => SetValue(PhoneProperty, value); }
private static readonly BindableProperty EmailProperty = BindableProperty.Create("EmailText", typeof(string), typeof(EditForm));
public string EmailText { get => (string)GetValue(EmailProperty); set => SetValue(EmailProperty, value); }
private static readonly BindableProperty DescriptionProperty = BindableProperty.Create("DescriptionText", typeof(string), typeof(EditForm));
public string DescriptionText { get => (string)GetValue(DescriptionProperty); set => SetValue(DescriptionProperty, value); }
public EditForm()
{
InitializeComponent();
BindingContext = this;
}
}
}
然后在视图中我回调我之前创建的表单并将数据绑定到可绑定的 属性,如下所示:
这是 xaml 文件:
<ContentPage xmlns:local="clr-namespace:ListContact.Extension"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ListContact.View.ListContactAddingForm">
<local:EditForm NameText="{Binding Name, Mode=TwoWay}" PhoneNumberText="egwebwev" EmailText="ưewevefqwf" DescriptionText="ewebe"/>
<ContentPage.Content>
<Button Text="Save"
HorizontalOptions="Center"
TextColor="White"
Command="{Binding AddContactCommand}"
BackgroundColor="#0A7CFF"/>
</ContentPage.Content>
</ContentPage>
这是背后的代码:
namespace ListContact.View
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class ListContactAddingForm : ContentPage
{
private SQLiteAsyncConnection connection;
public ListContactAddingForm()
{
connection = new SQLiteAsyncConnection(BaseConnection.DatabasePath);
ViewModel = new ContactViewModel(new PageService());
InitializeComponent();
}
private ContactViewModel ViewModel
{
get => BindingContext as ContactViewModel;
set => BindingContext = value;
}
}
}
`
这是我的视图模型:
namespace ListContact.ViewModel
{
public class ContactViewModel : BaseViewModel
{
public int Id { get; set; }
private string name;
public string Name
{
get => name;
set
{
SetValue(ref name, value);
}
}
private string description;
public string Description
{
get => description;
set
{
SetValue(ref description, value);
}
}
private string phoneNumber;
public string PhoneNumber
{
get => phoneNumber;
set
{
SetValue(ref phoneNumber, value);
}
}
private string email;
public string Email
{
get => email;
set
{
SetValue(ref email, value);
}
}
public ICommand AddContactCommand { get; private set; }
private IPageService pageService;
public object Alert { get; private set; }
public ContactViewModel(IPageService pageService)
{
this.pageService = pageService;
AddContactCommand = new Command(async () => await AddContacts());
}
private async Task AddContacts()
{
var newContact = new Contact()
{
Name = Name,
PhoneNumber = PhoneNumber,
Email = Email,
Description = Description
};
var result = await connection.InsertAsync(newContact);
if (result == 1)
await App.Current.MainPage.DisplayAlert("Successfully", "", "OK");
await pageService.PopAsycn();
}
}
}
但是当我 运行 这段代码时,我得到了错误:
No property, bindable property, or event found for "NameText", or mismatching type between value and property
在我将表单分离到另一个内容视图并从视图中调用它并遇到这个问题之前,我的代码没有问题
所以我的问题是:
我创建表单和可绑定 属性 的方式是否正确?
我可以将数据绑定到表单中的可绑定 属性 吗?如果可以怎么办?
以及如何修复上述错误?
我使用 MVVM 构建此代码
顺便说一句,抱歉我的英语不好
从 Xamarin.Forms Bindable Properties 开始,可以通过声明类型为 Bindable 的 public static readonly 属性 来创建可绑定的 属性 属性.
public static readonly BindableProperty NameTextProperty = BindableProperty.Create
("NameText", typeof(string), typeof(EditForm),"",BindingMode.OneWay,propertyChanged:NamePropertychanged);
然后你需要注意 Bindable属性 名称,例如 属性Name属性
public static readonly BindableProperty NameTextProperty = BindableProperty.Create
("NameText", typeof(string), typeof(EditForm),"",BindingMode.OneWay,propertyChanged:NamePropertychanged);
public string NameText
{
get => (string)GetValue(NameTextProperty);
set => SetValue(NameTextProperty, value);
}
最后,不需要在EditForm中使用Binding,只需要使用属性Changed事件来通知属性值已经改变。
private static void NamePropertychanged(BindableObject bindable, object oldValue, object newValue)
{
var control = (EditForm)bindable;
control.txtName.Text = (string)newValue;
}
做一个你可以看一看的例子:
EditForm xaml.
<ContentView.Content>
<StackLayout Padding="20">
<Label
FontSize="20"
HorizontalOptions="Center"
Text="Edit Contact Forms"
TextColor="Blue"
VerticalOptions="Start" />
<Label Text="Name" />
<Entry x:Name="txtName" Placeholder="Name" />
<Label Text="Phone number" />
<Entry
x:Name="txtPhoneNumber"
Keyboard="Telephone"
Placeholder="Phone number" />
<Label Text="Email" />
<Entry
x:Name="txtEmail"
Keyboard="Email"
Placeholder="Email" />
<Label Text="Description" />
<Editor
x:Name="txtDescription"
HeightRequest="70"
Placeholder="Description" />
</StackLayout>
</ContentView.Content>
public partial class EditForm : ContentView
{
public static readonly BindableProperty NameTextProperty = BindableProperty.Create
("NameText", typeof(string), typeof(EditForm),"",BindingMode.OneWay,propertyChanged:NamePropertychanged);
public string NameText
{
get => (string)GetValue(NameTextProperty);
set => SetValue(NameTextProperty, value);
}
public static readonly BindableProperty PhoneNumberTextProperty = BindableProperty.Create
("PhoneNumberText", typeof(string), typeof(EditForm),"",BindingMode.OneWay,propertyChanged:PhoneNumberchanged);
public string PhoneNumberText
{
get => (string)GetValue(PhoneNumberTextProperty);
set => SetValue(PhoneNumberTextProperty, value);
}
public static readonly BindableProperty EmailTextProperty = BindableProperty.Create
("EmailText", typeof(string), typeof(EditForm),"",BindingMode.OneWay,propertyChanged:Emailpropertychanged);
public string EmailText
{
get => (string)GetValue(EmailTextProperty);
set => SetValue(EmailTextProperty, value);
}
public static readonly BindableProperty DescriptionTextProperty = BindableProperty.Create
("DescriptionText", typeof(string), typeof(EditForm), "", BindingMode.OneWay, propertyChanged: Descriptionchanged);
public string DescriptionText
{
get => (string)GetValue(DescriptionTextProperty);
set => SetValue(DescriptionTextProperty, value);
}
private static void NamePropertychanged(BindableObject bindable, object oldValue, object newValue)
{
var control = (EditForm)bindable;
control.txtName.Text = (string)newValue;
}
private static void PhoneNumberchanged(BindableObject bindable, object oldValue, object newValue)
{
var control = (EditForm)bindable;
control.txtPhoneNumber.Text = (string)newValue;
}
private static void Emailpropertychanged(BindableObject bindable, object oldValue, object newValue)
{
var control = (EditForm)bindable;
control.txtEmail.Text = (string)newValue;
}
private static void Descriptionchanged(BindableObject bindable, object oldValue, object newValue)
{
var control = (EditForm)bindable;
control.txtDescription.Text = (string)newValue;
}
public EditForm()
{
InitializeComponent();
}
}
<StackLayout>
<local:EditForm
DescriptionText="{Binding option}"
EmailText="{Binding Email}"
NameText="{Binding Name}"
PhoneNumberText="{Binding Phone}" />
</StackLayout>
public partial class Page5 : ContentPage
{
public Contact contact1 { get; set; }
public Page5()
{
InitializeComponent();
contact1 = new Contact() { Name = "cherry", Phone = "1234567", Email = "xxxxxxxx", option = "this is test" };
this.BindingContext = contact1 ;
}
}
public class Contact:ViewModelBase
{
private string _name;
public string Name
{
get { return _name; }
set
{
_name = value;
RaisePropertyChanged("Name");
}
}
private string _phone;
public string Phone
{
get { return _phone; }
set
{
_phone = value;
RaisePropertyChanged("Phone");
}
}
private string _email;
public string Email
{
get { return _email; }
set
{
_email = value;
RaisePropertyChanged("Email");
}
}
private string _option;
public string option
{
get { return _option; }
set
{
_option = value;
RaisePropertyChanged("option");
}
}
}
实现 INotify 的 ViewModelBase属性已更改
public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
截图:
我有两个使用相同表单的页面,因此我创建了表单的内容视图并应用了如下可绑定属性:
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ListContact.Extension.EditForm">
<StackLayout Padding="20">
<Label Text="Edit Contact Forms"
HorizontalOptions="Center"
FontSize="20"
TextColor="Blue"
VerticalOptions="Start"/>
<Label Text="Name"/>
<Entry x:Name="txtName" Text="{Binding NameText}" Placeholder="Name"/>
<Label Text="Phone number"/>
<Entry x:Name="txtPhoneNumber" Text="{Binding PhoneNumberText}" Placeholder="Phone number" Keyboard="Telephone"/>
<Label Text="Email"/>
<Entry x:Name="txtEmail" Text="{Binding EmailText}" Placeholder="Email" Keyboard="Email"/>
<Label Text="Description"/>
<Editor x:Name="txtDescription" Text="{Binding DescriptionText}" Placeholder="Description"
HeightRequest="70"/>
</StackLayout>
</ContentView>
这是背后的代码:
using ListContact.ViewModel;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace ListContact.Extension
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class EditForm : ContentView
{
private static readonly BindableProperty NameProperty = BindableProperty.Create("NameText", typeof(object), typeof(EditForm));
public string NameText { get => (string)GetValue(NameProperty); set => SetValue(NameProperty, value); }
private static readonly BindableProperty PhoneProperty = BindableProperty.Create("PhoneNumberText", typeof(string), typeof(EditForm));
public string PhoneNumberText { get => (string)GetValue(PhoneProperty); set => SetValue(PhoneProperty, value); }
private static readonly BindableProperty EmailProperty = BindableProperty.Create("EmailText", typeof(string), typeof(EditForm));
public string EmailText { get => (string)GetValue(EmailProperty); set => SetValue(EmailProperty, value); }
private static readonly BindableProperty DescriptionProperty = BindableProperty.Create("DescriptionText", typeof(string), typeof(EditForm));
public string DescriptionText { get => (string)GetValue(DescriptionProperty); set => SetValue(DescriptionProperty, value); }
public EditForm()
{
InitializeComponent();
BindingContext = this;
}
}
}
然后在视图中我回调我之前创建的表单并将数据绑定到可绑定的 属性,如下所示:
这是 xaml 文件:
<ContentPage xmlns:local="clr-namespace:ListContact.Extension"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ListContact.View.ListContactAddingForm">
<local:EditForm NameText="{Binding Name, Mode=TwoWay}" PhoneNumberText="egwebwev" EmailText="ưewevefqwf" DescriptionText="ewebe"/>
<ContentPage.Content>
<Button Text="Save"
HorizontalOptions="Center"
TextColor="White"
Command="{Binding AddContactCommand}"
BackgroundColor="#0A7CFF"/>
</ContentPage.Content>
</ContentPage>
这是背后的代码:
namespace ListContact.View
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class ListContactAddingForm : ContentPage
{
private SQLiteAsyncConnection connection;
public ListContactAddingForm()
{
connection = new SQLiteAsyncConnection(BaseConnection.DatabasePath);
ViewModel = new ContactViewModel(new PageService());
InitializeComponent();
}
private ContactViewModel ViewModel
{
get => BindingContext as ContactViewModel;
set => BindingContext = value;
}
}
}
`
这是我的视图模型:
namespace ListContact.ViewModel
{
public class ContactViewModel : BaseViewModel
{
public int Id { get; set; }
private string name;
public string Name
{
get => name;
set
{
SetValue(ref name, value);
}
}
private string description;
public string Description
{
get => description;
set
{
SetValue(ref description, value);
}
}
private string phoneNumber;
public string PhoneNumber
{
get => phoneNumber;
set
{
SetValue(ref phoneNumber, value);
}
}
private string email;
public string Email
{
get => email;
set
{
SetValue(ref email, value);
}
}
public ICommand AddContactCommand { get; private set; }
private IPageService pageService;
public object Alert { get; private set; }
public ContactViewModel(IPageService pageService)
{
this.pageService = pageService;
AddContactCommand = new Command(async () => await AddContacts());
}
private async Task AddContacts()
{
var newContact = new Contact()
{
Name = Name,
PhoneNumber = PhoneNumber,
Email = Email,
Description = Description
};
var result = await connection.InsertAsync(newContact);
if (result == 1)
await App.Current.MainPage.DisplayAlert("Successfully", "", "OK");
await pageService.PopAsycn();
}
}
}
但是当我 运行 这段代码时,我得到了错误:
No property, bindable property, or event found for "NameText", or mismatching type between value and property
在我将表单分离到另一个内容视图并从视图中调用它并遇到这个问题之前,我的代码没有问题
所以我的问题是: 我创建表单和可绑定 属性 的方式是否正确? 我可以将数据绑定到表单中的可绑定 属性 吗?如果可以怎么办? 以及如何修复上述错误?
我使用 MVVM 构建此代码
顺便说一句,抱歉我的英语不好
从 Xamarin.Forms Bindable Properties 开始,可以通过声明类型为 Bindable 的 public static readonly 属性 来创建可绑定的 属性 属性.
public static readonly BindableProperty NameTextProperty = BindableProperty.Create
("NameText", typeof(string), typeof(EditForm),"",BindingMode.OneWay,propertyChanged:NamePropertychanged);
然后你需要注意 Bindable属性 名称,例如 属性Name属性
public static readonly BindableProperty NameTextProperty = BindableProperty.Create
("NameText", typeof(string), typeof(EditForm),"",BindingMode.OneWay,propertyChanged:NamePropertychanged);
public string NameText
{
get => (string)GetValue(NameTextProperty);
set => SetValue(NameTextProperty, value);
}
最后,不需要在EditForm中使用Binding,只需要使用属性Changed事件来通知属性值已经改变。
private static void NamePropertychanged(BindableObject bindable, object oldValue, object newValue)
{
var control = (EditForm)bindable;
control.txtName.Text = (string)newValue;
}
做一个你可以看一看的例子:
EditForm xaml.
<ContentView.Content>
<StackLayout Padding="20">
<Label
FontSize="20"
HorizontalOptions="Center"
Text="Edit Contact Forms"
TextColor="Blue"
VerticalOptions="Start" />
<Label Text="Name" />
<Entry x:Name="txtName" Placeholder="Name" />
<Label Text="Phone number" />
<Entry
x:Name="txtPhoneNumber"
Keyboard="Telephone"
Placeholder="Phone number" />
<Label Text="Email" />
<Entry
x:Name="txtEmail"
Keyboard="Email"
Placeholder="Email" />
<Label Text="Description" />
<Editor
x:Name="txtDescription"
HeightRequest="70"
Placeholder="Description" />
</StackLayout>
</ContentView.Content>
public partial class EditForm : ContentView
{
public static readonly BindableProperty NameTextProperty = BindableProperty.Create
("NameText", typeof(string), typeof(EditForm),"",BindingMode.OneWay,propertyChanged:NamePropertychanged);
public string NameText
{
get => (string)GetValue(NameTextProperty);
set => SetValue(NameTextProperty, value);
}
public static readonly BindableProperty PhoneNumberTextProperty = BindableProperty.Create
("PhoneNumberText", typeof(string), typeof(EditForm),"",BindingMode.OneWay,propertyChanged:PhoneNumberchanged);
public string PhoneNumberText
{
get => (string)GetValue(PhoneNumberTextProperty);
set => SetValue(PhoneNumberTextProperty, value);
}
public static readonly BindableProperty EmailTextProperty = BindableProperty.Create
("EmailText", typeof(string), typeof(EditForm),"",BindingMode.OneWay,propertyChanged:Emailpropertychanged);
public string EmailText
{
get => (string)GetValue(EmailTextProperty);
set => SetValue(EmailTextProperty, value);
}
public static readonly BindableProperty DescriptionTextProperty = BindableProperty.Create
("DescriptionText", typeof(string), typeof(EditForm), "", BindingMode.OneWay, propertyChanged: Descriptionchanged);
public string DescriptionText
{
get => (string)GetValue(DescriptionTextProperty);
set => SetValue(DescriptionTextProperty, value);
}
private static void NamePropertychanged(BindableObject bindable, object oldValue, object newValue)
{
var control = (EditForm)bindable;
control.txtName.Text = (string)newValue;
}
private static void PhoneNumberchanged(BindableObject bindable, object oldValue, object newValue)
{
var control = (EditForm)bindable;
control.txtPhoneNumber.Text = (string)newValue;
}
private static void Emailpropertychanged(BindableObject bindable, object oldValue, object newValue)
{
var control = (EditForm)bindable;
control.txtEmail.Text = (string)newValue;
}
private static void Descriptionchanged(BindableObject bindable, object oldValue, object newValue)
{
var control = (EditForm)bindable;
control.txtDescription.Text = (string)newValue;
}
public EditForm()
{
InitializeComponent();
}
}
<StackLayout>
<local:EditForm
DescriptionText="{Binding option}"
EmailText="{Binding Email}"
NameText="{Binding Name}"
PhoneNumberText="{Binding Phone}" />
</StackLayout>
public partial class Page5 : ContentPage
{
public Contact contact1 { get; set; }
public Page5()
{
InitializeComponent();
contact1 = new Contact() { Name = "cherry", Phone = "1234567", Email = "xxxxxxxx", option = "this is test" };
this.BindingContext = contact1 ;
}
}
public class Contact:ViewModelBase
{
private string _name;
public string Name
{
get { return _name; }
set
{
_name = value;
RaisePropertyChanged("Name");
}
}
private string _phone;
public string Phone
{
get { return _phone; }
set
{
_phone = value;
RaisePropertyChanged("Phone");
}
}
private string _email;
public string Email
{
get { return _email; }
set
{
_email = value;
RaisePropertyChanged("Email");
}
}
private string _option;
public string option
{
get { return _option; }
set
{
_option = value;
RaisePropertyChanged("option");
}
}
}
实现 INotify 的 ViewModelBase属性已更改
public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
截图: