如何监听DataContext更改以相应地调整UI状态

时间:2013-07-22 04:14:21

标签: iphone ios xamarin.ios mvvmcross

这个问题源自https://github.com/slodge/MvvmCross/issues/367线程内部的讨论。

如果我们遵循最近使用MvvmCross框架设置Bindings的示例,那么我们只需使用Bind(),To()扩展来设置绑定以控制属性(如UILabel.Text):

this.DelayBind(() => {
    var set = this.CreateBindingSet<KittenCollectionCell, Kitten>();
    set.Bind(NameLabel).To(kitten => kitten.Name);
    set.Bind(PriceLabel).To(kitten => kitten.Price);
    set.Bind(_loader).To(kitten => kitten.ImageUrl);
    set.Apply();
});

(摘自https://github.com/slodge/NPlus1DaysOfMvvmCross/blob/master/N-11-KittenView_Collections/KittenView.Touch/Views/KittenCollectionCell.cs

但是,如果我想根据DataContext中的某些值调整UI状态,该怎么办?例如,我想显示/隐藏一些按钮和标签,并调整一些约束值。

if (((UserInfo)DataContext).IsAdmin)
{
    SaveButton.Hidden = false;
    SecurityLabelConstraint.Constant = 50;

    /* etc */
}

如何监听DataContext更改事件?这里推荐的方法是什么?

感谢。

2 个答案:

答案 0 :(得分:0)

到目前为止,我决定将每个控件或约束绑定到DataContext的相应属性,例如:

this.DelayBind(() => {
    var set = this.CreateBindingSet<UserCell, UserInfo>();

    set.Bind(SecurityLabelConstraint).For(p => p.Constant).To(info => info.IsAdmin)
        .WithConversion(new ValueConverter<string>(s => s != null ? 20 : 0), null);

    // etc...

    set.Apply();
});

效果很好。

答案 1 :(得分:0)

有几种方法可以达到这个目的。

最简单的方法之一是您已经确定自己的方式 - 例如直接绑定SecurityLabelConstraint - 例如使用Tibet绑定:

set.Bind(SecurityLabelConstraint)
   .For(p => p.Constant)
   .To("If(info.IsAdmin, 20, 0)");

或者,如果需要复杂的逻辑(超出西藏绑定引擎的范围或性能),那么您可以实现对单元格上的属性的绑定 - 或者对中间对象的绑定。

例如,您可以使用Wrapper类来实现:

 public class Wrapper
 {
     private NSLayoutConstraint _constraint;
     public Wrapper(NSLayoutConstraint constraint)
     {
         _constraint = constraint;
     }

     private string _foo;
     public string Foo
     {
        get { return _foo; }
        set
        {
           _foo = value;
           // your complex logic on _constraint goes here
        }
     }
 }

如果您在单元格的字段中存储_wrapper实例,则可以将其绑定为:

set.Bind(_wrapper)
   .For(p => p.Foo)
   .To(info => info.IsAdmin);

如果您已将Foo属性放在单元格上,那么您可以使用:

set.Bind()
   .For(cell => cell.Foo)
   .To(info => info.IsAdmin);

实现绑定的最后一种方法是尝试直接挂钩单元格的DataContext并使用PropertyChanged处理程序 - 我不建议这样做,因为它往往有点繁琐维护,并且在访问NSObject的内部事件回调时很容易创建内存泄漏。