如何将对象作为可绑定属性传递给Xamarin.Forms自定义控件

3
如标题所示,我正在尝试将Person对象传递给自定义控件,而不是单独传递每个属性。
因此,这样做:
 <controls:PersonControl 
           Person="{Binding Person}"
           ControlTemplate="{StaticResource PersonControlTemplate}">
   </controls:PersonControl>

与此实现方式(参考这篇文章)相比,可以使用以下方式进行操作:

<controls:PersonControl 
       Name="{Binding Person.Name}"
       Age="{Binding Person.Age}" 
       ControlTemplate="{StaticResource PersonControlTemplate}">
</controls:PersonControl>

我尝试改变PersonControl代码后台中的bindable属性标识,但它没有起作用。实际上,我只得到了一个空白屏幕。

所以: 1-这是否可能(我知道这称为bindable property,但它也可以采取对象吗? 并且 2-如果不行,那么推荐的方法是什么?

我之所以想这样做是因为人物对象可能会随着时间增长而增加,我宁愿只更新自定义控件而不是消耗页面及其视图模型。

更新: 以下是PersonControl代码:

public partial class PersonControl : ContentView
    {

        public static readonly BindableProperty PersonProperty = BindableProperty.Create(
            nameof(Person),
            typeof(Person),
            typeof(PersonControl),
            string.Empty);

        public string Name
        {
            get { return this.Person.Name; }
        }

        public Person Person
        {
            get { return (Person)GetValue(PersonProperty); }
            set { SetValue(PersonProperty, value); }
        }

        public PersonControl()
        {
            InitializeComponent();
        } 

    }

以下是 PersonControl 的 XAML 代码:

<ContentView.Content>
     <StackLayout>
            <Label  Text="{TemplateBinding Person.Name, Mode=OneWay}"/>
      </StackLayout>
    </ContentView.Content>

最后是消耗页面:

 <ContentPage.Resources>
    <ControlTemplate x:Key="PersonControlTemplate">
        <controls:PersonControl></controls:PersonControl>
    </ControlTemplate>        
</ContentPage.Resources>

 <ContentPage.Content>
    <StackLayout Spacing="10" x:Name="layout">
        <controls:PersonControl
            Person="{Binding Person}"
             ControlTemplate="{StaticResource PersonControlTemplate}"></controls:PersonControl>
              </StackLayout>
</ContentPage.Content>

根据MVVM模式,person对象是页面视图模型上的属性。

更新:我按照这篇教程尝试将可绑定字符串类型替换为对象,但仍然没有成功。


1
是的,这是可能的。如果您能展示出您遇到问题的实际代码,那将会有所帮助。 - Jason
1
你需要修改你的所有代码。在你自己的代码中,你会有 "control.Name" 和 "control.Age",但是当你绑定 Person 时,你会有类似于 "control.Person.Name" 和 "control.Person.Age" 的内容。这只是一种假设,因为你还没有发布你的代码。 - Gusman
我已经更新了问题并附上了代码。谢谢。 - iKnowNothing
你发布的 XAML 是用于 ContentPage 而不是 ContentView。 - Jason
复制粘贴错误。我已经更新了代码。 - iKnowNothing
2个回答

1

是的,你可以。我使用了一个Entry,输入一些文本,然后将文本传输到ContentView中的标签。这里是运行的GIF。

enter image description here

首先,我添加了一个名为PersonName的属性,代码如下:

  public partial class PersonControl : ContentView
    {
        public PersonControl()
        {
            InitializeComponent();
        }

        public static BindableProperty PersonNameProperty = BindableProperty.Create(
                    propertyName: "PersonName",
                    returnType: typeof(string),
                    declaringType: typeof(PersonControl),
                    defaultValue: "",
                    defaultBindingMode: BindingMode.OneWay);

        public string PersonName
        {
            get { return (string)GetValue(PersonNameProperty); }
            set { SetValue(PersonNameProperty, value); } 
        }
    }

接下来是有关ContentView布局的代码。请不要忘记在ContentView标签中添加x:Name="ParentControl"

<ContentView xmlns="http://xamarin.com/schemas/2014/forms" 
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             mc:Ignorable="d"
              x:Name="ParentControl"
             x:Class="CustomDemoControl.PersonControl">
  <ContentView.Content>
        <StackLayout>
            <Label  Text="{Binding Source={x:Reference ParentControl}, Path=PersonName}"/>
        </StackLayout>
    </ContentView.Content>
</ContentView>

然后我在另一个页面中使用它。
 <StackLayout>
        <Entry x:Name="myEntry" Text="1"/>

        <local:PersonControl
             BindingContext="{x:Reference Name=myEntry}" 
              PersonName="{Binding Path=Text,  StringFormat='Welcome Mr {0}'}"
             ></local:PersonControl>
    </StackLayout>

这只传递单个属性而不是对象本身。虽然不是我想要的,但感谢您的输入。 - iKnowNothing

1
所以,结果发现答案是在可绑定属性签名中传递一个默认对象(在自定义控件的cs文件中),如下所示:
public static readonly BindableProperty PersonProperty =
           BindableProperty.Create(
               nameof(Person),
               typeof(Person),
               typeof(PersonProperty ),
               default(Person)); //this was the fix

现在,我错过了这个问题,因为我没有意识到控件中存在错误。它只是没有显示在输出窗口中。有人能指导我如何全面地调试Xamarin.Forms应用程序吗?或者至少在将来捕获这些类型的错误?谢谢。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接