在父项中设置绑定时,Xamarin.Forms 绑定到自定义控件不起作用

Posted

技术标签:

【中文标题】在父项中设置绑定时,Xamarin.Forms 绑定到自定义控件不起作用【英文标题】:Xamarin.Forms Binding to Custom Control Not Working When Binding Is Set In Parent 【发布时间】:2019-12-10 19:37:39 【问题描述】:

我正在尝试创建一个简单的 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" 这样的常量值时,它可以正常工作。我在 *** 上找到了this answer,尝试了以下方法,但也没有用(自定义控件 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" />

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

【问题讨论】:

【参考方案1】:

你找到的答案很好,我在我的图书馆里也是这样:

<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 的设置:

public TestControl()

    InitializeComponent();

    BindingContext = this; // Remove this line

【讨论】:

我正在尝试使用你的库,我觉得很难理解,没有一个简单的例子来说明如何使用它,更多的是你是如何制作它的。一些代码 sn-ps 没有显示完整的代码,最终不知道哪个是哪个,例如我不知道这个 github.com/roubachof/Sharpnado.Presentation.Forms/wiki/… 中的细节是什么 伙计,来吧,这里有一个完整的示例应用程序:github.com/roubachof/Xamarin-Forms-Practices 设法让它工作.. 玩弄它感谢这个。想在 shell 中使用它,最好的方法是什么?【参考方案2】:

我已经测试了你的代码,我们需要注意几个地方:

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>

您可以查看我测试的完整演示 here。

【讨论】:

【参考方案3】:

提供的答案工作正常。但是,这些要求您手动设置每个属性的绑定源。如果很多属性需要绑定,这可能会变得乏味。

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

要做到这一点,请按以下步骤操作:

    在代码隐藏文件中添加以下方法:

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

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

【讨论】:

以上是关于在父项中设置绑定时,Xamarin.Forms 绑定到自定义控件不起作用的主要内容,如果未能解决你的问题,请参考以下文章

Xamarin.Forms 在共享项目中设置图像源

Xamarin.Forms:有没有办法在xaml中设置派生样式的默认字体(系列)?

在Xamarin Forms中设置TableView宽度和高度

如何在Xamarin Forms中设置自动日/夜模式谷歌地图

无法在 UWP 中设置 SQLite 对象 - Xamarin Forms

如何在 Xamarin Forms 中以适当的图像比例在 UWP 中设置 SpashScreen?