繁体   English   中英

Xamarin表单用户控件绑定到ListView中

[英]Xamarin Forms User Control Binding inside ListView

场景-有一个ListView绑定到字符串的ObservableCollection。 Listview有一个标签和一个UserControl(仅包含一个标签)。 两者都绑定到同一集合。

另外,还有一个按钮可以为该集合生成一些随机数据。

问题是当我运行应用程序并单击“生成数据”按钮时,标签会更新,而UserControl不会更新。

下面是示例代码。

MainPage.xaml

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         xmlns:local="clr-namespace:TestSample"
         xmlns:controls="clr-namespace:TestSample.Controls"
         x:Class="TestSample.MainPage">

<StackLayout>
    <Button Text="Generate Data" Clicked="Button_Clicked"/>

    <ListView Grid.Row="1" HorizontalOptions="Center" ItemsSource="{Binding Collection}" SeparatorVisibility="None">
        <ListView.ItemTemplate>
            <DataTemplate>
                <ViewCell>
                    <StackLayout Orientation="Horizontal" HorizontalOptions="Center">
                        <Label Text="{Binding}"/>
                        <Label Text=" - "/>
                        <controls:MagicBox Text="{Binding}"/>
                    </StackLayout>
                </ViewCell>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</StackLayout>

MainPage.xaml.cs

 public partial class MainPage : ContentPage
{
    public ObservableCollection<string> Collection { get; set; }

    public MainPage()
    {
        InitializeComponent();
        Collection = new ObservableCollection<string>
        {
            "XX",
            "XX",
            "XX"
        };

        this.BindingContext = this;
    }

    public void Button_Clicked(object sender, EventArgs e)
    {
        var rand = new Random();
        for (int i = 0; i < 3; i++)
        {
            Collection[i] = rand.Next(10, 100).ToString();
        }
    }
}

用户控件

  <ContentView.Content>
  <Grid>
      <Label Text="{Binding Text}" />
  </Grid>

public partial class MagicBox : ContentView
{

    public static readonly BindableProperty TextProperty =
      BindableProperty.Create("Text", typeof(string), typeof(MagicBox), "XX");

    public string Text
    {
        get { return (string)GetValue(TextProperty); }
        set { SetValue(TextProperty, value); }
    }

    public MagicBox ()
    {
        InitializeComponent ();
        this.BindingContext = this;
    }
}

在实现INotifyPropertyChanged之后,我还尝试了POCO类的ObservableCollection而不是字符串,这没有用。 如果我将MagicBox文本直接绑定到字符串,则可以工作,但是如果将其绑定到某个属性,则不能工作。

在做

this.BindingContext = this;

在MagicBox.xaml.cs中,将BindingContext强制为当前对象。 这也意味着来自父级的BindingContext不再继承。

为了使其正常工作,请将您的代码更改为

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

    public static readonly BindableProperty TextProperty =
        BindableProperty.Create("Text", typeof(string), typeof(MagicBox), default(string));

    public string Text
    {
        get { return (string)GetValue(TextProperty); }
        set { SetValue(TextProperty, value); }
    }

    public MagicBox ()
    {
        InitializeComponent ();
    }
}

和你的XAML

<?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="TestSample.Controls.MagicBox"
         x:Name="box">
  <ContentView.Content>
    <Grid>
        <Label Text="{Binding Text, Source={x:Reference box}}" />
    </Grid>
  </ContentView.Content>
</ContentView>

我测试了 有用。

我认为问题是“ this.BindingContext = this;”这一行。 在您的自定义控件中。

您应该这样绑定:Text =“ {Binding Path = BindingContext,Source = {x:Reference ListViewName}}”

确保将x:Name添加到您的Listview。 没有经过测试,但希望它能对您有所帮助。

首先,更新您的自定义控件:

  • 更改您的“文本”依赖项属性定义=>将绑定模式设置为“ OneWay”,并添加propertyChanged事件处理程序,如下所示:

     public partial class MagicBox : ContentView { public static readonly BindableProperty TextProperty = BindableProperty.Create("Text", typeof(TextVM), typeof(MagicBox), "XX", BindingMode.OneWay, null, new BindableProperty.BindingPropertyChangedDelegate(TextPropertyChanged)); public TextVM Text { get { return (TextVM)GetValue(TextProperty); } set { SetValue(TextProperty, value); } } 
  • 然后像这样将'Text'propertyChanged方法添加到您的自定义控件中:

     private static void TextPropertyChanged(BindableObject sender, object oldValue, object newValue ) { Label updatedLabel = sender as Label; if(updatedLabel == null) return; updatedLabel.Text = (newValue as TextVM)?.MyText; } 

创建一个嵌入文本属性的Observable对象,以引发'PropertyChanged'事件:

public class TextVM : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private string _myText;
    public string MyText
    {
        get => _myText;
        set
        {
            _myText = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("MyText"));
        }
    }
}

然后在您的XAML中,更新文本绑定:

<controls:MagicBox Text="{Binding MyText}"/>

不要忘记更新您的收集类型和随机数生成过程...

应该不错!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM