How to bind arrays i mvvmcross

≡放荡痞女 提交于 2019-12-24 06:03:21

问题


I need a button to move in the view, when it is clicked. I have bind the the button in the following way (Android)

set.Bind(_paramsButton).For(pb => pb.LeftMargin).To(vm => vm.ButtonX).OneWay();
set.Bind(_paramsButton).For(pb => pb.TopMargin).To(vm => vm.ButtonY).OneWay();
set.Bind(_paramsButton).For(pb => pb.Height).To(vm => vm.ButtonHight).OneWay();
set.Bind(_paramsButton).For(pb => pb.Width).To(vm => vm.ButtonWidth).OneWay();

In the viewModel i have the 'normal' properties

private int _buttonX;
public int ButtonX
{

    get { return _buttonX; }
    set { _buttonX = value; RaisePropertyChanged(() => ButtonX); }

}

etc.

This is working fine. Now i have 10 buttons and want to bind like

for(int i=0; i<10; i++){ 

    set.Bind(_paramsButton[i]).For(pb => pb.LeftMargin).To(vm => vm.ButtonX[i]).OneWay();
    set.Bind(_paramsButton[i]).For(pb => pb.TopMargin).To(vm => vm.ButtonY[i]).OneWay();
    set.Bind(_paramsButton[i]).For(pb => pb.Height).To(vm => vm.ButtonHight[i]).OneWay();
    set.Bind(_paramsButton[i]).For(pb => pb.Width).To(vm => vm.ButtonWidth[i]).OneWay();

}

or

for(int i=0; i<10; i++){ 
    set.Bind(_paramsButton[i]).For(pb => pb.LeftMargin).To(vm => vm.Button[i].X).OneWay();
    set.Bind(_paramsButton[i]).For(pb => pb.TopMargin).To(vm => vm.Button[i].Y).OneWay();
    set.Bind(_paramsButton[i]).For(pb => pb.Height).To(vm => vm.Button[i].Height).OneWay();
    set.Bind(_paramsButton[i]).For(pb => pb.Width).To(vm => vm.Button[i].Width).OneWay();
}

My problem is in the viewModel, I don't know how to get the RaisePropertyChanged to fire on the individual items in the array list. Does anybody have an example on how to declare the integer array in the modelView?


回答1:


The general answer is that if you want to fire RaisePropertyChanged for a sub-viewModel, then the easiest way is to make that sub-viewModel support INotifyPropertyChanged

So, for example, you could have a ButtonViewModel subclass like:

 public class ButtonViewModel : MvxNotifyPropertyChanged
 {
      private int _x;
      public int X
      {
          get { return _x; }
          set { _x = value; RaisePropertyChanged(() => X); }
      }

      // etc
 }

and your page-level ViewModel could then store a List or ObservableCollection of those:

 public class MyViewModel : MvxViewModel
 {
      private readonly List<ButtonViewModel> _buttons;
      public List<ButtonViewModel> Buttons
      {
          get { return __buttons; }
      }

      // etc
 }

In general, this is the way to approach the problem - and this should allow the binding to work.


However... in the case of your specific code, there is another problem to consider.

Your binding statement includes a for-loop variable in the binding expression:

for(int i=0; i<10; i++){ 
    set.Bind(_paramsButton[i]).For(pb => pb.LeftMargin).To(vm => vm.Button[i].X).OneWay();
}

I'm afraid this simply won't work - MvvmCross's expression walking doesn't have any built-in evaluation for these types of local-variable expressions.

You could instead generate a string for the binding statement like:

for(int i=0; i<10; i++){ 
    var to = string.Format("Button[{0}].X", i);
    set.Bind(_paramsButton[i]).For(pb => pb.LeftMargin).To(to).OneWay();
}

As some other alternatives:

  • you could instead try using some kind of collection class for binding. For an example of this, see how the set of zombies is bound to map annotations in the second part of N=38 - http://slodge.blogspot.co.uk/2013/09/n38-more-maps-and-more-zombies.html
  • you could instead try setting up your button views as MvxView objects - each with their own internal bindings. For more on this idea, see N=32 in http://slodge.blogspot.co.uk/2013/06/n32-truth-about-viewmodels-starring.html


来源:https://stackoverflow.com/questions/19095020/how-to-bind-arrays-i-mvvmcross

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!