在 MvvmCross 中以编程方式创建和绑定 Android 个 Spinner
Programmatically creating and binding Android Spinners in MvvmCross
我正在构建一个需要动态生成和绑定 Spinner 控件的跨平台应用程序。我能够在 iOS 和 Windows 平台上做到这一点,但在 Android 上有问题。如果我理解正确,我必须将一些参数传递给 MvxSpinner 的构造函数 - 上下文和属性,但我无法弄清楚我该怎么做以及应该传递什么那里。另外,我不知道如何绑定 ItemsSource 和 SelectedItem。我想必须创建一个新的绑定集(类似于 iOS 版本),但我无法在 Android 上弄清楚。你能给我一些指示吗?
这是我的 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 );
}
}
这里是 iOS 版本(或多或少做同样的事情 - 虽然它只是清除现有的微调器而不是重新使用它们):
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();
}
我现在拥有的 Android 版本的部分(非功能性)大纲如下:
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();
}
这是一个关于如何通过 Activity.OnCreate 中的代码创建 mvxspinner 的示例:
_bindingContext = new MvxAndroidBindingContext(this, new LayoutInflaterProvider(LayoutInflater), _viewModel);
var view = (LinearLayout)_bindingContext.BindingInflate(Resource.Layout.Main, null);
SetContentView(view);
var spinner = new MvxSpinner(this, null, new MvxAdapter(this, _bindingContext));
view.AddView(spinner);
那么如果你想要你的 LayoutInflaterProvider 可能看起来像这样:
public class LayoutInflaterProvider
: IMvxLayoutInflater
{
public LayoutInflaterProvider(LayoutInflater layoutInflater)
{
LayoutInflater = layoutInflater;
}
public LayoutInflater LayoutInflater { get; private set; }
}
我最初是在看这个 tutorial。
我正在构建一个需要动态生成和绑定 Spinner 控件的跨平台应用程序。我能够在 iOS 和 Windows 平台上做到这一点,但在 Android 上有问题。如果我理解正确,我必须将一些参数传递给 MvxSpinner 的构造函数 - 上下文和属性,但我无法弄清楚我该怎么做以及应该传递什么那里。另外,我不知道如何绑定 ItemsSource 和 SelectedItem。我想必须创建一个新的绑定集(类似于 iOS 版本),但我无法在 Android 上弄清楚。你能给我一些指示吗?
这是我的 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 );
}
}
这里是 iOS 版本(或多或少做同样的事情 - 虽然它只是清除现有的微调器而不是重新使用它们):
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();
}
我现在拥有的 Android 版本的部分(非功能性)大纲如下:
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();
}
这是一个关于如何通过 Activity.OnCreate 中的代码创建 mvxspinner 的示例:
_bindingContext = new MvxAndroidBindingContext(this, new LayoutInflaterProvider(LayoutInflater), _viewModel);
var view = (LinearLayout)_bindingContext.BindingInflate(Resource.Layout.Main, null);
SetContentView(view);
var spinner = new MvxSpinner(this, null, new MvxAdapter(this, _bindingContext));
view.AddView(spinner);
那么如果你想要你的 LayoutInflaterProvider 可能看起来像这样:
public class LayoutInflaterProvider
: IMvxLayoutInflater
{
public LayoutInflaterProvider(LayoutInflater layoutInflater)
{
LayoutInflater = layoutInflater;
}
public LayoutInflater LayoutInflater { get; private set; }
}
我最初是在看这个 tutorial。