场景 - 有一个ListView绑定到ObservableCollection的字符串。 Listview有一个标签和一个UserControl(只包含一个标签)。两者都绑定到同一个集合。
此外,还有一个按钮可为集合生成一些随机数据。
问题是,当我运行应用程序并单击Generate Data按钮时,标签会更新,但不会更新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 Text直接绑定到字符串,它可以工作,但如果我将它绑定到某个属性则不行。
答案 0 :(得分:2)
操作
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>
我测试了它。它有效。
答案 1 :(得分:0)
我认为问题在于&#34; this.BindingContext = this;&#34;在您的自定义控件中。
你应该这样绑定: Text =&#34; {Binding Path = BindingContext,Source = {x:Reference ListViewName}}&#34;
确保将x:Name添加到Listview。没有经过测试,但希望它可以帮到你。
答案 2 :(得分:0)
首先,更新您的自定义控件:
更改您的&#34;文字&#34;依赖属性定义=&gt;将绑定模式设置为&#34; OneWay&#34;并添加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); }
}
然后添加&#39;文字&#39; 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;
}
创建一个嵌入text属性的Observable对象,以便抛出&#39; PropertyChanged&#39;事件:
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}"/>
不要忘记更新您的收藏类型和随机数生成流程......
应该很好!