【问题标题】:How to pass object as bindable property to Xamarin.Forms custom control如何将对象作为可绑定属性传递给 Xamarin.Forms 自定义控件
【发布时间】:2020-06-10 21:35:14
【问题描述】:

正如标题所示,我试图将 Person 对象传递给自定义控件,而不是分别传递每个属性。

所以:

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

而不是这个(基于this 实现)

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

我已尝试更改 PersonControl 代码后面的可绑定属性签名,但它不起作用。我实际上只是得到一个空白屏幕。

所以: 1 - 这甚至可能吗(我知道它被称为 可绑定属性 但它也需要对象吗? 和 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 对象是页面视图模型上的一个属性。 提前感谢您的帮助。

更新:我遵循了这个tutorial 并尝试用一个对象替换可绑定的字符串类型,但仍然没有乐趣

【问题讨论】:

  • 是的,这是可能的。如果您向我们展示您遇到问题的实际代码会有所帮助
  • 你需要修改你所有的代码,它为你工作的方式你会有“control.Name”和“control.Age”,但是当你绑定Person时你会得到类似“control.Age”的东西。 Person.Name”和“control.Person.Age”。这是所有假设,因为您尚未发布代码。
  • 我已经用代码更新了这个问题。谢谢
  • 您发布的 XAML 用于 ContentPage,而不是 ContentView
  • 复制粘贴错误。我已经更新了代码

标签: c# mobile mvvm xamarin.forms user-controls


【解决方案1】:

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

首先,我添加一个名为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>

【讨论】:

  • 这会传入单个属性而不是对象本身。不是我想要的,但感谢您的输入
【解决方案2】:

所以,答案是在可绑定属性签名中(在自定义控件的 cs 中)传递一个默认对象,如下所示:

public static readonly BindableProperty PersonProperty =
           BindableProperty.Create(
               nameof(Person),
               typeof(Person),
               typeof(PersonProperty ),
               default(Person)); //this was the fix

现在,我错过了这个,因为我没有意识到控件中的错误。它只是没有出现在输出窗口中。谁能指出如何正确全面调试 xamarin.forms 应用程序的方向?或者至少在未来发现这些错误? 谢谢

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多