自定义Usercontrol和ViewModel之间的绑定在Xamarin中不起作用?

时间:2016-09-21 07:08:43

标签: c# mvvm xamarin

我在我的应用程序中创建了一个自定义用户控件,我尝试将其属性(BindableProperty)绑定到ViewModel,但它对我不起作用。难道我做错了什么? 这是用户控件。它只是用于测试项目的自定义步进器:"减少"并且"增加"按钮和它们之间的数量标签。 请注意,usercontrol内部的绑定工作正常(例如命令绑定)。我想要做的是将QuantityProperty绑定到ViewModel

namespace UsercontrolBindingTest.Usercontrols
{
    using System.Windows.Input;
    using Xamarin.Forms;

    public class CustomQuantityStepper : ContentView
    {
        public static readonly BindableProperty QuantityProperty =
            BindableProperty.Create(nameof(Quantity), typeof(int), typeof(CustomQuantityStepper), 0, BindingMode.TwoWay);

        public int Quantity
        {
            get
            {
                return (int)base.GetValue(QuantityProperty);
            }

            set
            {
                base.SetValue(QuantityProperty, value);
                this.OnPropertyChanged(nameof(this.Quantity));
            }
        }

        public ICommand DecreaseQuantityCommand { get; private set; }

        public ICommand IncreaseQuantityCommand { get; private set; }

        public CustomQuantityStepper()
        {
            this.BindingContext = this;

            this.DecreaseQuantityCommand = new Command(() => this.Quantity--);
            this.IncreaseQuantityCommand = new Command(() => this.Quantity++);

            this.DrawControl();
        }

        private void DrawControl()
        {
            var quantityEntry = new Entry();
            quantityEntry.SetBinding(Entry.TextProperty, new Binding("Quantity", BindingMode.TwoWay));
            quantityEntry.WidthRequest = 50;
            quantityEntry.HorizontalTextAlignment = TextAlignment.Center;

            var increaseQuantityButton = new Button { Text = "+" };
            increaseQuantityButton.SetBinding(Button.CommandProperty, "IncreaseQuantityCommand");

            var decreaseQuantityButton = new Button { Text = "-" }; 
            decreaseQuantityButton.SetBinding(Button.CommandProperty, "DecreaseQuantityCommand");

            var ui = new StackLayout()
            {
                Orientation = StackOrientation.Horizontal,
                Children =
                {
                    decreaseQuantityButton,
                    quantityEntry,
                    increaseQuantityButton
                }
            };

            this.Content = ui;
        }
    }
}

视图证明View和VM之间的绑定正在起作用:

namespace UsercontrolBindingTest
{
    using Usercontrols;
    using Xamarin.Forms;

    public class App : Application
    {
        public App()
        {
            MainPage = new ContentPage
            {
                BindingContext = new MainPageVM(),
                Content = new StackLayout
                {
                    VerticalOptions = LayoutOptions.Center,
                    HorizontalOptions = LayoutOptions.Center,
                    Children =
                    {
                        this.GetLabel("Title"),
                        this.GetCustomStepper(),
                        this.GetLabel("SelectedQuantity")
                    }
                }
            };
        }

        private Label GetLabel(string boundedPropertyName)
        {
            var ret = new Label();
            ret.HorizontalOptions = LayoutOptions.CenterAndExpand;
            ret.SetBinding(Label.TextProperty, new Binding(boundedPropertyName));

            return ret;
        }

        private CustomQuantityStepper GetCustomStepper()
        {
            var ret = new CustomQuantityStepper();
            var dataContext = this.BindingContext as MainPageVM;

            ret.SetBinding(CustomQuantityStepper.QuantityProperty, new Binding("SelectedQuantity", BindingMode.TwoWay));

            return ret;
        }
    }
}

我的简单ViewModel:

namespace UsercontrolBindingTest
{
    using System.ComponentModel;

    internal class MainPageVM : INotifyPropertyChanged
    {
        private int _selectedQuantity;

        public int SelectedQuantity
        {
            get
            {
                return this._selectedQuantity;
            }

            set
            {
                this._selectedQuantity = value;
                this.NotifyPropertyChanged(nameof(this.SelectedQuantity));
            }
        }

        public string Title { get; set; } = "ViewModel is bound";

        public MainPageVM()
        {
            this.SelectedQuantity = 0;
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged(string propName)
        {
            this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
        }
    }
}

我已经检查了很多不同的topis和博客帖子,但我无法找到解决方案。希望在这里得到帮助...... 附加示例项目:https://1drv.ms/u/s!Apu16I9kXJFtl28YBjkfwDztT9j0

1 个答案:

答案 0 :(得分:0)

您要将BindingContext的{​​{1}}设置为自身(CustomQuantityStepper)。这就是为什么绑定引擎正在寻找一个名为" SelectedQuantity"在自定义控件中,不在中的ViewModel。

  • 不要在控件中设置this,而是让它使用当前定义的上下文(希望)指向VM。
  • 设置BindingContext的{​​{1}} property,让它指向正确的来源(即VM)。