问题
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
MvxViewobjects - 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