使用SetBinding进行Xamarin.Forms绑定无效

3

我有一个基础的自定义控件:

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); }
    }
}

我从这个类中继承并设置绑定上下文:
public partial class FeedbackView : TabItem
{
   public FeedbackView(FeedbackViewModel viewModel)
   {
       InitializeComponent();    
       Content.BindingContext = viewModel;    
   }
}

这是视图模型:

 public class FeedbackViewModel : BaseViewModel
 {
     private string header;

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

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

当我运行它时,头部未绑定到视图模型属性。我有什么明显忘记的东西吗?或者我做错了什么?

似乎您忘了在“FeedbackViewModel”中实现“INotifyPropertyChanged”。 - Wosi
@Wosi 抱歉,我忘记了我的 FeedbackViewModel 是从 BaseViewModel 类继承的,其中已经实现了 INotifyPropertyChanged。我已经在问题中编辑了代码。 - Alexei Malashkevich
2个回答

1
由于您没有分享FeedbackViewXAML部分,因此只能猜测,但让我们尝试一下:
您说:

header not binds to viewmodel's property

从您分享的代码中,我非常确定TabItemHeader属性已经设置,即使您的绑定方式不是常规的。这是问题吗?还是您的问题是屏幕上没有显示任何内容?
解决“没有显示任何内容”的问题需要对您的代码进行一些更改。首先,在BindableProperty.Create上设置propertyChanged参数。
public static readonly BindableProperty HeaderProperty =
    BindableProperty.Create("Header", typeof(string), typeof(TabItem), default(string),
    propertyChanged: OnHeaderChanged);

实现它,并创建一个虚方法,以便您可以在子视图中覆盖它。
static void OnHeaderChanged (BindableObject bindable, object oldValue, object newvalue)
{
    ((TabItem)bindable).OnHeaderChanged ((string)oldValue, (string)newValue);
}

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

现在,在您派生的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;
}

这应该能让你入门。

最后需要注意的是,我想说在TabItem构造函数中设置绑定是不寻常的。它会破坏MVVM模式,因为视图(TabItem)对视图模型的结构(以及Header属性的存在)做出了一些假设。

通常情况下,该绑定是在TabItem集成实例上设置的。

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

或者,将VM作为构造函数参数传递已经破坏了MVVM,您最终可以在FeedbackView的构造函数中执行此操作。
这是我的个人意见。请不要在没有我参与的情况下开始激烈讨论。

0

为什么我不能在控件本身内定义绑定?我还更新了问题中的代码。现在正确吗? - Alexei Malashkevich
控件不知道任何关于“ViewModel”的信息。绑定属性的名称对于“BindableProperty”并不重要。否则,“TextView.TextProperty”只能绑定到名为“text”的属性,而不能绑定到“CustomerViewModel.LastName”或“UserViewModel.EmailAddress”。绑定是在“Page”或其“XAML”文件中完成的。这是“ViewModel”和“Control”之间的连接。因此,您的实现仍然是错误的。阅读博客文章,您将看到差异。 - Wosi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接