I have a Model class Person
, which has some string properties. In the UI, there are some Entry
fields that, when a button is pressed, does the following in a ViewModel class:
我有一个Model类Person,它有一些字符串属性。在用户界面中,当按下按钮时,在ViewModel类中有一些输入字段执行以下操作:
creates a Person
object with the values from the fields populating the object's properties
使用填充对象属性的字段中的值创建Person对象
adds the Person
object to an ObservableList<Person>
, which itself is created in the constructor of the ViewModel class
将Person对象添加到ObservableList
,该对象本身是在ViewModel类的构造函数中创建的
I then try to display some of the Person
object's properties in a CollectionView
list. A list of the string values. I'd like it to look something like this:
然后,我尝试在CollectionView列表中显示Person对象的一些属性。字符串值的列表。我希望它看起来像这样:
I know that both the Person
object is being created and the ObservableList<Person>
list is being populated, as I can see the values when I step through the code.
我知道Person对象正在被创建,ObservableList
列表正在被填充,因为我在单步执行代码时可以看到这些值。
Person.cs
Person.cs
namespace BindingDemo.Model
{
public partial class Person : ObservableObject
{
#region PersonObjectProperties
[ObservableProperty]
private string firstName;
[ObservableProperty]
private string lastName;
[ObservableProperty]
private string email;
[ObservableProperty]
private string password;
#endregion PersonObjectProperties
public void ClearFields()
{
FirstName = string.Empty;
LastName = string.Empty;
Email = string.Empty;
Password = string.Empty;
}
}
}
ViewModel class:
ViewModel类:
using BindingDemo.Model;
namespace BindingDemo.ViewModel
{
public partial class MainPageViewModel : ObservableObject
{
public Person Person { get; } = new Person();
[ObservableProperty]
private ObservableCollection<Person> persons;
public MainPageViewModel()
{
persons = new ObservableCollection<Person>();
}
[RelayCommand]
private void AddPersonToListAndDb()
{
// every field must have a value
if (string.IsNullOrWhiteSpace(Person.FirstName) ||
string.IsNullOrWhiteSpace(Person.LastName) ||
string.IsNullOrWhiteSpace(Person.Email) ||
string.IsNullOrWhiteSpace(Person.Password))
return;
// add the Person object to the list of Person objects
Persons.Add(Person);
// clear the fields in the UI so the user can add another person
Person.ClearFields();
// add the Person object to a database
}
}
}
View class:
查看类:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="BindingDemo.MainPage"
Title="Create Person"
xmlns:viewmodel="clr-namespace:BindingDemo.ViewModel"
x:DataType="viewmodel:MainPageViewModel">
<Grid RowDefinitions="Auto, Auto, Auto, Auto, Auto,*"
Margin="10">
<Entry Grid.Row ="0"
Placeholder="Enter your first name"
PlaceholderColor="DarkGoldenrod"
FontAttributes="Bold"
Text="{Binding Person.FirstName}" />
<Entry Grid.Row="1"
Placeholder="Enter your last name"
PlaceholderColor="DarkGoldenrod"
FontAttributes="Bold"
Text="{Binding Person.LastName}" />
<Entry Grid.Row="2"
Placeholder="Enter your email address"
PlaceholderColor="DarkGoldenrod"
FontAttributes="Bold"
Text="{Binding Person.Email}" />
<Entry Grid.Row="3"
Placeholder="Enter your password"
PlaceholderColor="DarkGoldenrod"
FontAttributes="Bold"
IsPassword="True"
Text="{Binding Person.Password}" />
<Button Grid.Row="4"
Margin="10"
Text="Add to Database"
FontAttributes="Bold"
HorizontalOptions="Center"
Command="{Binding AddPersonToListAndDbCommand}"/>
<CollectionView Grid.Row="5"
ItemsSource="{Binding Persons}">
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout Margin="5">
<HorizontalStackLayout>
<Label Text="First name:" />
<Label Text="{Binding Person.FirstName}" />
</HorizontalStackLayout>
<HorizontalStackLayout>
<Label Text="Last name:" />
<Label Text="{Binding Person.LastName}" />
</HorizontalStackLayout>
<HorizontalStackLayout>
<Label Text="Email address: " />
<Label Text="{Binding Person.Email}" />
</HorizontalStackLayout>
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</Grid>
</ContentPage>
The problem is most likely in the Binding, but I don't know what else to try.
问题很可能出在绑定上,但我不知道还能尝试什么。
When I'm debugging, I hover my mouse over over the Text={Binding Person.FirstName}
to see the value of Person.FirstName
. Well, if I hover over Person
I can drill down into the object and all the correct values are there, but when I hover over FirstName
, it gives the error children could not be evaluated
.
当我调试时,我将鼠标悬停在文本={BindingPerson.FirstName}上,以查看Person.FirstName的值。嗯,如果我将鼠标悬停在Person上,我可以向下钻取到对象,所有正确的值都在那里,但当我将鼠标悬停在FirstName上时,它会给出错误:无法评估子代。
To illustrate that the list of Person
objects is being created, here is an image of a watch, after I've created a few objects and put them into the list:
为了说明正在创建Person对象列表,在我创建了几个对象并将它们放入列表之后,下面是一个手表的图像:
EDIT: this is my MainPage.xaml.cs code:
编辑:这是我的MainPage.xaml.cs代码:
using BindingDemo.ViewModel;
namespace BindingDemo
{
public partial class MainPage : ContentPage
{
public MainPage(MainPageViewModel mainPageViewModel)
{
InitializeComponent();
BindingContext = mainPageViewModel;
}
}
}
更多回答
The proper binding expression would be “{Binding FirstName}”
正确的绑定表达式应该是“{bindingFirstName}”
Where do you set the BindingContext
? There should be a BindingContext = new MainPageViewModel();
in your code behind ctor (with reservation for that you use Dependency Injection).
在哪里设置BindingContext?在ctor后面的代码中应该有一个BindingContext=new MainPageViewModel();(保留使用依赖项注入)。
@Jason that doesn't work.
@杰森,这不管用。
@PeterWessberg I do have that.
@PeterWessberg我确实有这种感觉。
@PeterWessberg I actually set the BindingContext in the xaml.,cs. public MainPage(MainPageViewModel mv) { InitializeComponent(); BindingContext=mv;}
@PeterWessberg我实际上在XAML.,cs中设置了BindingContext。公共主页(MainPageViewModel MV){InitializeComponent();BindingContext=MV;}
because your ItemsSource
is an IEnumerable<Person>
, each row of the CollectionView
has a BindingContext
of the current Person
object
因为您的ItemsSource是IEumable
,所以CollectionView的每一行都有当前Person对象的BindingContext
that means the binding expression in the DataTemplate
would be relative to a Person
object, ie
这意味着数据模板中的绑定表达式将相对于Person对象,即
Text="{Binding FirstName}"
however, because you are using compiled bindings, you also need to specify the DataType
但是,由于您使用的是已编译的绑定,因此还需要指定dataType
<DataTemplate x:DataType="model:Person">
you will also need to add an xmlns
declaration for model
您还需要为模型添加一个xmlns声明
更多回答
Hi Jason! I tried your suggestion. Perhaps I didn't do the last part correctly, where you said to "add an xmlns declaration for 'model'. I'm assuming you meant to add this line to the '<ContentPage/>' element? 'xmlns:model="clr-namespace:ProjectName.Model"'?
嗨,杰森!我试过你的建议了。也许我没有正确完成最后一部分,您说的是“为‘Model’添加一个xmlns声明。我猜您的意思是要将此行添加到‘’元素中?”‘xmlns:model=“clr-namespace:ProjectName.Model”’?
because I tried that (and the rest of your suggestion), and... nothing. Same broken behavior. Can you expand upon the statement "add an xmlns declaration for model"?
因为我试过了(还有你其余的建议),然后...没什么。同样的行为失控。您能对“为模型添加一个xmlns声明”这句话做进一步的阐述吗?
Are you getting the exact same error message?
您是否收到了完全相同的错误消息?
I don't get an error message. Nothing appears in the Label text.
我没有收到错误消息。标签文本中不显示任何内容。
That is, the value for "Text={Binding FirstName}" is an empty string.
也就是说,“Text={bindingFirstName}”的值是空字符串。
我是一名优秀的程序员,十分优秀!