微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

何时使用Xamarin绑定,而不是将对象传递给页面构造函数? 在PersonCard中在“个人列表”中在应用程序中

如何解决何时使用Xamarin绑定,而不是将对象传递给页面构造函数? 在PersonCard中在“个人列表”中在应用程序中

因此,我遇到了一个问题,我想以一种我认为非常标准的方式在应用程序中传递数据,但是我找不到与我想做的事情相似的示例或示例。

例如,我有一个类型为person的应用程序。

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>

enter image description here

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。