我的目标是创建一个包含基本Entry控件的用户控件,该控件将更新视图模型中的指定属性。 除非视图模型属性名称与用户控件中的属性完全相同,否则我无法将用户控件绑定到视图模型中的属性名称。这违背了可重复使用的双向可重用控制的目的。 我怀疑我只是错过了一个关键概念。
我的期望是我应该能够将一个或多个UserEditors添加到页面并将其绑定到视图模型中的各种字符串属性,UserEditor获取/设置的属性应该是我在UserEditor的{Binding}。
我创建了一个简单的PCL项目来测试。如果有人能够让我走上正确的轨道,我将非常感激。我已经用尽所有其他资源来掌握这个。我可以提供VS2015解决方案的zip文件,但是它的大小(65MB)包含所有XAM内容。
以下是所有部分:
UserEditor.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="UserControl.UserEditor">
<ContentView.Content>
<StackLayout Orientation="Vertical" Margin="0,0,0,10" >
<Entry x:Name="TextEntry"
Text="{Binding Text}"
HorizontalOptions="Fill"/>
</StackLayout>
</ContentView.Content>
</ContentView>
UserEditor.xaml.cs
using System;
using System.Linq;
using Xamarin.Forms;
namespace UserControl
{
public partial class UserEditor : ContentView
{
//Bindable property for Text
public static readonly BindableProperty TextProperty =
BindableProperty.Create("Text",
typeof(string),
typeof(UserEditor),
string.Empty,
BindingMode.TwoWay,
null,
OnTextPropertyChanged,
null,
null,
null);
public static void OnTextPropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
var control = bindable as UserEditor;
if (control == null) return;
control.TextEntry.Text = newValue.ToString();
}
public UserEditor()
{
InitializeComponent();
}
public string Text
{
get
{
return (string)GetValue(TextProperty);
}
set
{
SetValue(TextProperty, value);
}
}
}
}
MainPageViewModel.cs
using System;
using System.ComponentModel;
using System.Linq;
namespace UserControl
{
class MainPageViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public MainPageViewModel()
{
}
protected void OnPropertyChanged(string name)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
string textProperyInVM = "Initial value";
public string TextPropertyInVm
{
get
{
return textProperyInVM;
}
set
{
textProperyInVM = value;
OnPropertyChanged("TextPropertyInVm");
}
}
}
}
MainPage.xaml中
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:UserControl"
x:Class="UserControl.MainPage">
<!--//Page binding context is set to the view model in the page contructor.-->
<StackLayout Orientation="Vertical">
<Label Text="Binding viewmodel properties to user control" />
<!--//Label is bound to ViewModel field named TextPropertyInVm-->
<Label Text="{Binding TextPropertyInVm}" ></Label>
<!--//UserEditor custom control is bound to ViewModel field named TextPropertyInVm
//User editor will not see the view model property.
//User editor ALWAYS wants to work with a property named "Text"
//User editor neither reads nor updates the view model property specified in the Binding -->
<!--
Text changes in the user control cause this error:
[0:] Binding: 'Text' property not found on 'UserControl.MainPageViewModel', target property: 'Xamarin.Forms.Entry.Text'
-->
<local:UserEditor Text="{Binding TextPropertyInVm, Mode=TwoWay}"> </local:UserEditor>
</StackLayout>
</ContentPage>
MainPage.xaml.cs中
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
namespace UserControl
{
public partial class MainPage : ContentPage
{
private MainPageViewModel vm;
public MainPage()
{
InitializeComponent();
//instantiate and bind this page to a new view model.
vm = new MainPageViewModel();
this.BindingContext = vm;
}
}
}
答案 0 :(得分:2)
<强> EDITED 强>
有两个问题:
在UserEditor绑定中有一个拼写错误:TextPropertyInVM而不是TextPropertyInVm。
您需要在UserEditor构造函数中的TextEntry上设置BindingContext,以便XAML知道要绑定的对象:
public UserEditor() { 的InitializeComponent(); TextEntry.BindingContext = this; }
无论何时想要使用Binding,都需要确保在正确的范围内正确设置BindingContext。
UserEditor本身的BindingContext用于解决在MainPage中使用的Binding表达式(这是答案原始版本中的错误)。但是,UserEntry.xaml中的Binding表达式本身需要查看UserEntry类的上下文,而不是视图模型(或者它从其所在页面继承的任何BindingContext)。因此,需要在UserEntry内的某个范围内设置BindingContext,这将影响Entry元素。