Xamarin.Forms中绑定自定义控件时,当绑定在父级中设置时无法工作

3

我正在尝试创建一个简单的Xamarin.Forms自定义控件,并遇到了绑定问题。

这是我的初始自定义控件:

<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:Class="CubisMobile.Controls.TestControl"
         x:Name="TestControlView">
<Label Text="{Binding TestText}" />

public partial class TestControl : ContentView
{
    public static readonly BindableProperty TestTextProperty = BindableProperty.Create(nameof(TestText), typeof(string), typeof(TestControl));
    public string TestText
    {
        get { return (string)GetValue(TestTextProperty); }
        set { SetValue(TestTextProperty, value); }
    }

    public TestControl()
    {
        InitializeComponent();

        BindingContext = this;
    }
}

我正在尝试这样使用它:

...
<StackLayout>
    <controls:TestControl TestText="{Binding Title}" />
    <Label Text="{Binding Title}" />
</StackLayout>
...

我添加了第二个标签来测试Title属性是否正常工作,结果它是正常的。 但是文本不会显示在自定义控件上。当我设置一个固定值时,例如 TestText="Testing" 它就按预期运行。我在 StackOverflow 上找到了 这个答案,尝试了下面的方法,但也没有起作用(自定义控件XAML):

<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:Class="CubisMobile.Controls.TestControl"
         x:Name="TestControlView">
<Label Text="{Binding Source={x:Reference TestControlView}, Path=TestText}" />

我真的不明白为什么这个绑定没起作用。
3个回答

3
你找到的答案是正确的,我在我的库中也是这样做的:最初的回答。
<tabs:TabItem x:Class="Sharpnado.Presentation.Forms.CustomViews.Tabs.UnderlinedTabItem"
          xmlns="http://xamarin.com/schemas/2014/forms"
          xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
          xmlns:tabs="clr-namespace:Sharpnado.Presentation.Forms.CustomViews.Tabs;assembly=Sharpnado.Presentation.Forms"
          x:Name="RootLayout">

<ContentView.Content>
    <Grid BackgroundColor="Transparent">

        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>

        <Label Style="{StaticResource TabTextHeader}"
               FontFamily="{Binding Source={x:Reference RootLayout}, Path=FontFamily}"
               FontSize="{Binding Source={x:Reference RootLayout}, Path=LabelSize}"
               Text="{Binding Source={x:Reference RootLayout}, Path=Label}"
               TextColor="{Binding Source={x:Reference RootLayout}, Path=UnselectedLabelColor}">

"最初的回答":代码如下:

代码实现:

    public static readonly BindableProperty FontFamilyProperty = BindableProperty.Create(
        nameof(FontFamily),
        typeof(string),
        typeof(TabItem),
        null,
        BindingMode.OneWay);

    public string FontFamily
    {
        get => (string)GetValue(FontFamilyProperty);
        set => SetValue(FontFamilyProperty, value);
    }

我看到你展示的代码中唯一的问题是BindingContext的设置:

我认为你展示的代码中唯一的问题在于BindingContext的设置:

public TestControl()
{
    InitializeComponent();

    BindingContext = this; // Remove this line
}

我试图使用你的库,但很难理解,没有简单的示例说明如何使用它,只是介绍了它的实现方式。有些代码片段没有显示完整的代码,最终不知道哪个是哪个,例如我不知道这个链接中的“details”指的是什么:https://github.com/roubachof/Sharpnado.Presentation.Forms/wiki/Pure-Xamarin.Forms-tabs - Siphamandla Ngwenya
兄弟,看这里,这里有一个完整的示例应用程序:https://github.com/roubachof/Xamarin-Forms-Practices - Roubachof
成功让它工作了,玩弄它感谢这个。想在shell内使用它,最好的方法是什么? - Siphamandla Ngwenya

1

我已经测试了你的代码,我们需要注意以下几点:

1. 假设 ContentView 的类名为 TestControl,你可以尝试如下代码:

 <?xml version="1.0" encoding="UTF-8"?>
 <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:Class="CustomeViewApp1.controls.TestControl"
         x:Name="TestControlView"
         >
<ContentView.Content>
    <Label Text="{Binding Source={x:Reference TestControlView}, Path=TestText}" />
</ContentView.Content>

2.TestControl.xaml.cs 中删除代码 BindingContext = this;

[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class TestControl : ContentView
{

    public static readonly BindableProperty TestTextProperty = BindableProperty.Create(nameof(TestText), typeof(string), typeof(TestControl));
    public string TestText
    {
        get { return (string)GetValue(TestTextProperty); }
        set { SetValue(TestTextProperty, value); }
    }

    public TestControl()
    {
        InitializeComponent();

        //BindingContext = this;
    }

}

我使用的测试XAML如下所示:

  <StackLayout Orientation="Horizontal" HorizontalOptions="Center">
     <controls:TestControl TestText="{Binding Title}"  VerticalOptions="Center"/>
     <Label Text="{Binding Type}" FontSize="Medium" TextColor="#F0BB7F" 
     FontAttributes="Bold" VerticalOptions="Center"/>
  </StackLayout>

你可以在这里查看我测试的完整演示链接


-1

提供的答案很好。但是,这些需要您手动设置每个属性的绑定源。如果有很多属性需要绑定,这可能会变得繁琐。

一个更简单的方法是覆盖框架公开的OnChildAdded事件,并在那里设置绑定上下文。这将自动为添加的任何子项设置绑定上下文。

要执行此操作,请按照以下步骤操作:

  1. 在代码后台文件中添加以下方法:

    protected override void OnChildAdded(Xamarin.Forms.Element child) { base.OnChildAdded(child); //必须调用基本实现 child.BindingContext = this; //这将为添加的子项设置绑定上下文 }

  2. 在xaml中将控件绑定到公共可绑定属性。例如:


需要您手动为每个属性设置绑定源。- 不,如果一个元素没有设置其BindingContext,那么它会自动查找父级(以及父级的父级等),直到找到一个BindingContext。它会使用找到的那个绑定源。 - ToolmakerSteve
不需要,如果一个元素没有设置其BindingContext,它会自动查找父级(以及父级的父级等),直到找到一个BindingContext。这就是被使用的内容。 - undefined

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