我在将Xamarin表单中的自定义视图中的数据绑定到包含页面的视图模型时遇到问题。
我的自定义视图非常简单,一对代表键值对的标签:
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="KeyValueView">
<Grid VerticalOptions="Start">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Label x:Name="KeyLabel" Text="{Binding Key}" Grid.Column="0" HorizontalOptions="Start" />
<Label x:Name="ValueLabel" Text="{Binding Value}" Grid.Column="1" HorizontalOptions="EndAndExpand" />
</Grid>
</ContentView>
后面的代码:
public partial class KeyValueView : ContentView
{
public KeyValueView()
{
InitializeComponent();
this.VerticalOptions = LayoutOptions.Start;
this.BindingContext = this;
}
public static readonly BindableProperty ValueProperty =
BindableProperty.Create<KeyValueView, string>(w => w.Value, default(string));
public string Value
{
get {return (string)GetValue(ValueProperty);}
set {SetValue(ValueProperty, value);}
}
public static readonly BindableProperty KeyProperty =
BindableProperty.Create<KeyValueView, string>(w => w.Key, default(string));
public string Key
{
get {return (string)GetValue(KeyProperty);}
set {SetValue(KeyProperty, value);}
}
}
这在页面中使用如下:
<views:KeyValueView Key="Order Number" Value="{Binding document_number}" />
问题是Key字符串是按预期显示的,但值字符串不是。 我试过在document_number属性上强制一个PropertyChanged事件,这没有帮助。 我还尝试在自定义视图的键/值属性的设置器中显式设置标签上的Text属性:
public string Key
{
get {return (string)GetValue(KeyProperty);}
set {
SetValue(KeyProperty, value);
KeyLabel.Text = value;
}
}
再次这没有帮助,setter代码似乎永远不会被执行(我在它上面设置了一个断点并且没有被击中)
如果我添加一个开箱即用的控件,例如直接绑定到页面中属性的标签,则会正确显示:
<Label Text="{Binding document_number}"/>
<views:KeyValueView Key="Order Number" Value="{Binding document_number}" />
任何人都可以解释为什么会发生这种情况(或者更确切地说没有发生)吗?
答案 0 :(得分:23)
不要在自定义控件内部分配绑定。使用此:
public partial class KeyValueView : ContentView
{
public KeyValueView()
{
InitializeComponent();
this.VerticalOptions = LayoutOptions.Start;
}
public static readonly BindableProperty ValueProperty =
BindableProperty.Create<KeyValueView, string>(w => w.Value, default(string));
public string Value
{
get {return (string)GetValue(ValueProperty);}
set {SetValue(ValueProperty, value);}
}
public static readonly BindableProperty KeyProperty =
BindableProperty.Create<KeyValueView, string>(w => w.Key, default(string));
public string Key
{
get {return (string)GetValue(KeyProperty);}
set {SetValue(KeyProperty, value);}
}
protected override void OnPropertyChanged(string propertyName)
{
base.OnPropertyChanged(propertyName);
if (propertyName == ValueProperty.PropertyName)
{
ValueLabel.Text = Value;
}
if (propertyName == KeyProperty.PropertyName)
{
KeyLabel.Text = Key;
}
}
}
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="KeyValueView">
<Grid VerticalOptions="Start">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Label x:Name="KeyLabel" Grid.Column="0" HorizontalOptions="Start" />
<Label x:Name="ValueLabel" Grid.Column="1" HorizontalOptions="EndAndExpand" />
</Grid>
</ContentView>
将属性(例如,值)视为对BindableProperty(ValueProperty)的引用。如果您在Value setter中执行某些操作,BindableProperty将无法收到有关它的通知,如果您使用BindableProperty(分配/更改ValueProperty)执行操作则相反 - 属性值setter将无法调用。
如果你想处理PropertyChanged,你可以覆盖它(OnPropertyChanged)或Actions(作为创建BindableProperty时的附加参数)。
答案 1 :(得分:0)
我能够通过
让这个工作public KeyValueView()
{
InitializeComponent();
this.VerticalOptions = LayoutOptions.Start;
this.Content.BindingContext = this;
}
然后在xaml.cs中为您使用自定义视图的视图执行此操作:
public ParentView()
{
InitializeComponent();
BindingContext = this;
}
对于一个给我带来问题的Entry字段,我必须确保defaultBindingMode参数设置为TwoWay。