简体   繁体   English

使用SetBinding的Xamarin.Forms绑定无法正常工作

[英]Xamarin.Forms binding using SetBinding not working

I have base custom control: 我有基本自定义控件:

public class TabItem : ContentView
{
    public TabItem()
    {
        SetBinding(HeaderProperty, new Binding("Header"));
    }

    public static readonly BindableProperty HeaderProperty =
        BindableProperty.Create("Header", typeof(string), typeof(TabItem), default(string));

    public string Header
    {
        get { return (string)GetValue(TabItem.HeaderProperty); }
        set { SetValue(TabItem.HeaderProperty, value); }
    }
}

I derive from this class and set Binding context: 我派生自这个类并设置Binding上下文:

public partial class FeedbackView : TabItem
{
   public FeedbackView(FeedbackViewModel viewModel)
   {
       InitializeComponent();    
       Content.BindingContext = viewModel;    
   }
}

This is view model: 这是视图模型:

 public class FeedbackViewModel : BaseViewModel
 {
     private string header;

     public FeedbackViewModel()
     {
         Header = "Test Header";
     }

     public string Header
     {
         get { return header; }
         set
         {
             header = value;
             OnPropertyChanged("Header");
         }
      }

When I run it - header not binds to viewmodel's property. 当我运行它时 - 标题不绑定到viewmodel的属性。 Is there something obvious that I forgot? 有什么明显的东西我忘记了吗? Or I'm doing something wrong? 或者我做错了什么?

As you do not share the XAML part of FeedbackView , one can only guess, but let's try nonetheless: 由于您不共享FeedbackViewXAML部分,因此我们只能猜测,但让我们尝试一下:

you say: 你说:

header not binds to viewmodel's property header不绑定到viewmodel的属性

I'm quite sure (from the code you've shared) the Header property of TabItem is set, even if your way of doing binding is unconventional. 我很确定(从您共享的代码中)设置TabItemHeader属性,即使您的绑定方式是非常规的。 Is this the issue ? 这是问题吗? or your issue is that you don't have anything displayed on screen ? 或者你的问题是屏幕上没有显示任何内容?

Solving the "nothing displayed" issue require some changes to your code. 解决“未显示”问题需要对代码进行一些更改。 First, set the propertyChanged arg on BindableProperty.Create 首先,在BindableProperty.Create上设置propertyChanged arg

public static readonly BindableProperty HeaderProperty =
    BindableProperty.Create("Header", typeof(string), typeof(TabItem), default(string),
    propertyChanged: OnHeaderChanged);

implements it, and create a virtual method so you can override it in your subviews 实现它,并创建一个虚拟方法,以便您可以在子视图中覆盖它

static void OnHeaderChanged (BindableObject bindable, object oldValue, object newvalue)
{
    ((TabItem)bindable).OnHeaderChanged ((string)oldValue, (string)newValue);
}

protected virtual void OnHeaderChanged (string oldValue, string newValue)
{
}

Now, in your derived FeedbackView , you can override OnHeaderChanged and set the label according to the Header 现在,在派生的FeedbackView ,您可以覆盖OnHeaderChanged并根据Header设置标签

protected override void OnHeaderChanged (string oldValue, string newValue)
{
    //headerLabel is defined in Xaml, and has a x:Name="headerLabel"
    headerLabel.Text = newValue;
}

This should get you started. 这应该让你开始。

As a last note, I'd say that setting the Binding in the TabItem ctor is, well, unconventional. 作为最后一点,我会说在TabItem ctor中设置Binding是非常规的。 It breaks the MVVM pattern as the View (TabItem) makes some assumption about the structure of the ViewModel (and the existence of an Header property). 它打破了MVVM模式,因为View(TabItem)对ViewModel的结构做了一些假设(并且存在Header属性)。

That binding is normally set on the TabItem inherited instance. 该绑定通常在TabItem继承的实例上设置。

var feedback = new FeedbackView (myVm);
feedback.SetBinding (TabItem.HeaderProperty, "Header");

or, as passing the VM as ctor parameter already breaks MVVM, you could eventually do that in FeedbackView ctor. 或者,当作为ctor参数传递VM已经破坏 MVVM时,您最终可以在FeedbackView ctor中执行此操作。

This last part is my humble opinion. 最后一部分是我的拙见。 Don't start a heated discussion about it, or do it without me involved :) 不要开始热烈的讨论,或者没有我参与:)

Your implementation of BindableProperty is wrong. 您对BindableProperty实现是错误的。 Look here how to do it right: https://blog.xamarin.com/using-custom-controls-in-xamarin.forms-on-android/ 看看这里如何正确做到: https//blog.xamarin.com/using-custom-controls-in-xamarin.forms-on-android/

The Binding to the property is usually done inside Page . Binding到属性通常在Page内完成。 There you bind the property of your ViewModel to the control's BindableProperty . 在那里,您将ViewModel的属性绑定到控件的BindableProperty You don't do it inside the control itself. 你不是在控件本身内部做的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM