Xamarin表单无法使用双向绑定创建用户控件以查看模型属性名称

时间:2016-12-07 04:48:32

标签: xamarin xamarin.forms

我的目标是创建一个包含基本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;
    }
  }
}

1 个答案:

答案 0 :(得分:2)

<强> EDITED

有两个问题:

    在MainPage.xaml中,
  1. 在UserEditor绑定中有一个拼写错误:TextPropertyInVM而不是TextPropertyInVm。

  2. 您需要在UserEditor构造函数中的TextEntry上设置BindingContext,以便XAML知道要绑定的对象:

    public UserEditor() {     的InitializeComponent();     TextEntry.BindingContext = this; }

  3. 无论何时想要使用Binding,都需要确保在正确的范围内正确设置BindingContext。

    UserEditor本身的BindingContext用于解决在MainPage中使用的Binding表达式(这是答案原始版本中的错误)。但是,UserEntry.xaml中的Binding表达式本身需要查看UserEntry类的上下文,而不是视图模型(或者它从其所在页面继承的任何BindingContext)。因此,需要在UserEntry内的某个范围内设置BindingContext,这将影响Entry元素。