Sto creando un'applicazione multipiattaforma che richiede la generazione dinamica e il binding dei controlli Spinner. Sono stato in grado di farlo su piattaforme iOS e Windows, ma ho problemi con Android. Se ho capito bene, devo passare alcuni argomenti al costruttore di MvxSpinner - contesto e attrs, ma non sono in grado di capire come posso farlo e cosa dovrebbe essere passato lì. Inoltre, non so come legare quindi ItemsSource e SelectedItem. Suppongo che debba essere creato un nuovo set di binding (in modo simile alla versione iOS), ma non sono in grado di capirlo su Android. Puoi per favore darmi delle indicazioni?Creazione programmatica e associazione di spinners Android in MvvmCross
Ecco il mio codice sorgente dalla versione di Windows:
private void InputColourAtlasChangedMessageHandler(InputColourAtlasChangedMessage message)
{
ColourAtlas selected = message.SelectedColourAtlas;
var vm = ViewModel as ColorMatchViewModel;
List<ComboBox> newComboboxes = new List<ComboBox>();
var currentCount = ColourPickersContainer.Children.Count;
for (int i = currentCount; i < message.ColourCodePartCount; i++)
{
ComboBox cb = new ComboBox { Margin = new Thickness(0, 0, 10, 0), PlaceholderText = "choose" };
Binding itemsSourceBinding = new Binding();
itemsSourceBinding.Path = new PropertyPath("ColourPartLists[" + i + "]");
Binding selectedItemBinding = new Binding();
selectedItemBinding.Path = new PropertyPath("SelectedColourCodeParts[" + i + "]");
selectedItemBinding.Mode = BindingMode.TwoWay;
cb.Tag = i;
ColourPickersContainer.Children.Add(cb);
cb.SetBinding(ComboBox.ItemsSourceProperty, itemsSourceBinding);
cb.SetBinding(ComboBox.SelectedItemProperty, selectedItemBinding);
cb.SelectionChanged += cb_SelectionChanged;
BindingOperations.SetBinding(cb, ComboBox.SelectedItemProperty, selectedItemBinding);
newComboboxes.Add(cb);
}
while (ColourPickersContainer.Children.Count > message.ColourCodePartCount)
{
ColourPickersContainer.Children.RemoveAt(ColourPickersContainer.Children.Count - 1);
}
_comboboxes = newComboboxes;
}
void cb_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var cb = sender as ComboBox;
int changedIndex = (int)cb.Tag;
if (e.AddedItems.Count > 0)
{
(DataContext as ColorMatchViewModel).ColourCodePartChangedCommand.Execute(changedIndex);
}
}
Ed ecco la versione iOS (facendo più o meno la stessa cosa - anche se solo cancella i filatori esistenti invece di riutilizzo):
private void InputColourAtlasChangedMessageHandler(InputColourAtlasChangedMessage message)
{
ColourAtlas selected = message.SelectedColourAtlas;
ClearPickers();
var currentSet = this.CreateBindingSet<ColorMatchView, ColorMatchViewModel>();
for (int i = 0; i < message.ColourCodePartCount; i++)
{
var j = i;
UIPickerView picker = new UIPickerView();
var pickerViewModel = new MvxPickerViewModel(picker);
picker.Model = pickerViewModel;
picker.ShowSelectionIndicator = true;
pickerViewModel.SelectedItemChanged += vm_SelectedItemChanged;
var textView = new PaddedUITextField(new RectangleF(10, 50 + i * 40, 300, 30));
Add(textView);
textView.InputView = picker;
_pickers.Add(picker);
_textViews.Add(textView);
currentSet.Bind(textView).For(t => t.Text).To("SelectedColourCodeParts[" + i + "]");
currentSet.Bind(pickerViewModel).For(p => p.ItemsSource).To("ColourPartLists[" + i + "]");
currentSet.Bind(pickerViewModel).For(p => p.SelectedItem).To("SelectedColourCodeParts[" + i + "]");
currentSet.Bind(pickerViewModel).For(p => p.SelectedChangedCommand).To(vm => vm.ColourCodePartChangedCommand).CommandParameter(j);
}
currentSet.Apply();
UpdateLayout(View.Frame.Size);
}
private void ClearPickers()
{
foreach (var picker in _pickers)
{
var vm = picker.Model as MvxPickerViewModel;
vm.SelectedItemChanged -= vm_SelectedItemChanged;
picker.RemoveFromSuperview();
}
foreach (var textView in _textViews)
{
textView.RemoveFromSuperview();
}
_pickers.Clear();
_textViews.Clear();
}
parziale (e non funzionale) schema per la versione Android che ho adesso è la seguente:
private void InputColourAtlasChangedMessageHandler(InputColourAtlasChangedMessage message)
{
ColourAtlas selected = message.SelectedColourAtlas;
var layout = FindViewById<LinearLayout>(Resource.Id.spinnerList);
ClearPickers();
for (int i = 0; i < message.ColourCodePartCount; i++)
{
MvxSpinner spinner = new MvxSpinner(Context??, Attrs??);
MvxAdapter adapter = new MvxAdapter(this);
spinner.ItemSelected += spinner_ItemSelected;
layout.AddView(spinner);
_spinners.Add(spinner);
}
}
void spinner_ItemSelected(object sender, AdapterView.ItemSelectedEventArgs e)
{
var changedIndex = _spinners.IndexOf(sender as MvxSpinner);
(DataContext as ColorMatchViewModel).ColourCodePartChangedCommand.Execute(changedIndex);
}
private void ClearPickers()
{
var layout = FindViewById<LinearLayout>(Resource.Id.spinnerList);
foreach (var spinner in _spinners)
{
spinner.ItemSelected -= spinner_ItemSelected;
}
layout.RemoveAllViews();
_spinners.Clear();
}
https://github.com/MvvmCross/MvvmCross-Tutorials/blob/master/ApiExamples/ApiExamples.Touch/Views/FirstView.cs#L138 e https://github.com/MvvmCross/MvvmCross-Tutorials/blob /master/ApiExamples/ApiExamples.Droid/Resources/Layout/Test_Spinner.axml#L11 - entrambi utilizzano l'associazione dati anziché il codice. – Stuart
Grazie a Stuart, questo mi dà la soluzione alla parte vincolante dei dati della domanda, ma ho ancora problemi con la creazione progressiva di MvxSpinner nel codice. Come può essere fatto? Cosa dovrebbe essere passato al suo costruttore? –