How to bind arrays i mvvmcross

2019-08-01 05:37发布

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条回答
神经病院院长
2楼-- · 2019-08-01 06:08

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:

查看更多
登录 后发表回答