如何解决何时使用Xamarin绑定,而不是将对象传递给页面构造函数? 在PersonCard中在“个人列表”中在应用程序中
因此,我遇到了一个问题,我想以一种我认为非常标准的方式在应用程序中传递数据,但是我找不到与我想做的事情相似的示例或示例。
public class Person
{
public string Name;
public int Age;
public Person(string name,int age)
{
Name = name;
Age = age;
}
}
我想创建一个人卡列表,每个卡都显示该人的信息。然后,当点击该卡时,它将带您到包含该人的信息的新页面。我已经在下面的代码中实现了此功能,但是我尝试过的xamarin原理不起作用,因此它更多地依赖于我的c#技能,我觉得这不是编写xamarin代码的标准方法。
我已将工作项目上传到GitHub repo。
所以我的问题是,我的方法的缺点是什么,以及如何使用更标准的工具(如绑定)来实现相同的功能。
PersonCard.xaml:
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="CustomViewListTest.Views.PersonCard"
xmlns:System="clr-namespace:System;assembly=mscorlib">
<ContentView.ControlTemplate>
<ControlTemplate>
<Frame BorderColor="#3F3F3F" Margin="2">
<Frame.GestureRecognizers>
<TapGestureRecognizer Tapped="OnTapped"/>
</Frame.GestureRecognizers>
<StackLayout>
<Label Text="{TemplateBinding Name}"></Label>
<Label Text="{TemplateBinding Age}"></Label>
</StackLayout>
</Frame>
</ControlTemplate>
</ContentView.ControlTemplate>
</ContentView>
PersonCard.cs
[XamlCompilation(XamlCompilationoptions.Compile)] 公共局部类PersonCard:ContentView {
public PersonCard(Person person)
{
Person = person;
InitializeComponent();
}
public PersonCard()
{
InitializeComponent();
}
public static readonly BindableProperty PersonProperty =
BindableProperty.Create(nameof(Person),typeof(Person),typeof(PersonCard),null);
public static readonly BindableProperty NameProperty =
BindableProperty.Create(nameof(Name),typeof(string),string.Empty);
public static readonly BindableProperty AgeProperty =
BindableProperty.Create(nameof(Age),string.Empty);
public Person Person
{
get => (Person)GetValue(PersonProperty);
set => SetValue(PersonProperty,value);
}
public string Name
{
get { return Person.Name; }
}
public string Age
{
get { return Person.Age.ToString(); }
}
async void OnTapped(object sender,EventArgs args)
{
Page page = new NavigationPage(new PersonFullView(Person));
await Navigation.PushAsync(new NavigationPage(page));
}
}
PersonFullView.xaml
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="CustomViewListTest.Views.PersonFullView"
xmlns:views ="clr-namespace:CustomViewListTest.Views">
<StackLayout>
<Label Text="This page shows a person's details"></Label>
<Label x:Name="PersonName"></Label>
<Label x:Name="PersonAge"></Label>
<Label Text="End"></Label>
</StackLayout>
</ContentPage>
PersonFullView.cs
[XamlCompilation(XamlCompilationoptions.Compile)]
public partial class PersonFullView : ContentPage
{
public PersonFullView()
{
InitializeComponent();
}
public Person Person;
public PersonFullView(Person person)
{
Person = person;
InitializeComponent();
PersonName.Text = person.Name;
PersonAge.Text = person.Age.ToString();
}
public static readonly BindableProperty NameProperty =
BindableProperty.Create(nameof(Name),typeof(PersonFullView),"No name");
public static readonly BindableProperty AgeProperty =
BindableProperty.Create(nameof(Age),"No age");
public string Name
{
get { return Person.Name; }
}
public string Age
{
get { return Person.Age.ToString(); }
}
}
PersonList.xaml
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="CustomViewListTest.Views.PersonList"
xmlns:views ="clr-namespace:CustomViewListTest.Views">
<StackLayout x:Name="personStack">
<Label Text="List of People"></Label>
</StackLayout>
</ContentPage>
PersonList.cs
[XamlCompilation(XamlCompilationoptions.Compile)]
public partial class PersonList : ContentPage
{
public PersonList()
{
InitializeComponent();
}
public List<Person> People;
public List<PersonCard> cards { get; set; }
public PersonList(List<Person> people)
{
InitializeComponent();
People = people;
cards = new List<PersonCard>();
foreach (var p in people)
{
personStack.Children.Add(new PersonCard(p));
}
BindingContext = this;
}
}
它的工作方式是在personList中定义2个Person对象,然后使用采用Person对象的PersonCard构造函数来创建卡片。我使用了stackLayout,因为我无法获得与我希望使用的相同功能来使用列表视图。我认为问题源于列表视图无法容纳contentviews,而是包含对象列表,并且您为其提供了可绑定的模板。我无法正常工作。
您可能还注意到我得到了可绑定属性,适用于PersonCard,但不适用于PersonFullView。我尝试为后者使用基本相同的代码,但无济于事。我认为关于启动时不存在的页面上的可绑定属性的某些内容很糟糕。
因此,我很好奇如何使用绑定来实现此目的,而不是为视图和页面创建非参数构造函数,而在任何示例中我都没有真正看到过。另外,我对将尽可能多的逻辑移至xaml文件感兴趣。显然,您可以从后面的cs文件中完成所有操作,但是我发现很难正确布局。
解决方法
由于您已使用数据绑定,因此最好在ViewModel中处理逻辑(填充数据和导航),并使用 Command 而不是 Click Event 。>
此外,我有兴趣将尽可能多的逻辑转移到xaml文件中
我无法使用相同的功能来使用列表视图,这是我所希望的。
因此您可以修改和改进如下代码。我使用了 ListView 来显示数据。
在PersonCard中
MyAggregate
using CustomViewListTest.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace CustomViewListTest.Views
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class PersonCard : ContentView
{
public PersonCard()
{
InitializeComponent();
}
public static readonly BindableProperty NameProperty =
BindableProperty.Create(nameof(Name),typeof(string),typeof(PersonCard),string.Empty);
public static readonly BindableProperty AgeProperty =
BindableProperty.Create(nameof(Age),string.Empty);
public string Name
{
get => (string)GetValue(NameProperty);
set => SetValue(NameProperty,value);
}
public string Age
{
get => (string)GetValue(AgeProperty);
set => SetValue(AgeProperty,value);
}
public static readonly BindableProperty ClickCommandProperty =
BindableProperty.Create(nameof(ClickCommand),typeof(ICommand),typeof(PersonCard));
public ICommand ClickCommand
{
get => (ICommand)GetValue(ClickCommandProperty);
set => SetValue(ClickCommandProperty,value);
}
public static BindableProperty ClickParameterProperty =
BindableProperty.Create(nameof(ClickParameter),typeof(object),typeof(PersonCard));
public object ClickParameter
{
get => (object)GetValue(ClickParameterProperty);
set => SetValue(ClickParameterProperty,value);
}
}
}
在“个人列表”中
<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="CustomViewListTest.Views.PersonCard"
xmlns:System="clr-namespace:System;assembly=mscorlib"
x:Name="card"
>
<ContentView.Content>
<Frame BorderColor="#3F3F3F" Padding="0" Margin="2">
<Frame.GestureRecognizers>
<TapGestureRecognizer Command="{Binding ClickCommand,Source={x:Reference card}}" CommandParameter="{Binding ClickParameter,Source={x:Reference card}}"/>
</Frame.GestureRecognizers>
<StackLayout Orientation="Horizontal">
<Label Text="{Binding Name,Source={x:Reference card}}" TextColor="Red"></Label>
<Label Text="{Binding Age,Source={x:Reference card}}" TextColor="Green"></Label>
</StackLayout>
</Frame>
</ContentView.Content>
</ContentView>
using CustomViewListTest.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections.ObjectModel;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
using System.Windows.Input;
namespace CustomViewListTest.Views
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class PersonList : ContentPage
{
public PersonList()
{
InitializeComponent();
BindingContext = new MyViewModel(this.Navigation);
}
}
public class MyViewModel
{
public ICommand ClickCommand { get; private set; }
INavigation CurrentNavigation;
public ObservableCollection<Person> MyItems {get;set;}
public MyViewModel( INavigation navigation)
{
CurrentNavigation = navigation;
MyItems = new ObservableCollection<Person>() { new Person("Jack",23),new Person("Lucas",25) };
ClickCommand = new Command(async (org) =>
{
var item = org as Person;
PersonFullView page = new PersonFullView(item);
await CurrentNavigation.PushAsync(page);
});
}
}
}
在应用程序中
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="CustomViewListTest.Views.PersonList"
xmlns:views ="clr-namespace:CustomViewListTest.Views"
x:Name="page"
>
<StackLayout>
<ListView ItemsSource="{Binding MyItems}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<views:PersonCard Name="{Binding Name}" Age="{Binding Age}" ClickCommand="{Binding Path=BindingContext.ClickCommand,Source={x:Reference page}}" ClickParameter="{Binding .}" />
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage>
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。