SelectedItem
先週、ビルドでのダニエルの講演の準備中に、ドロイドの欠如が問題として特定されました。
それを回避するために、いくつかの簡単な答えがありました:
1SelectedItemPosition
バインディングに使用できるものがあります-これはint
2使用するClick
ICommand/IMvxCommand
代わりにバインディングを使用できますSelectedItem
-あなたの例では、これは同じaxmlになりますが、
public IMvxCommand ShowItemCommand
{
get
{
return new MvxRelayCommand<Address>(address => DoShowContact(address));
}
}
上記のこのオプションを明確Click
にするために、私が使用するものです。
SelectedItemが本当に必要な場合...
次に、完全な答えを得るために、ダニエルと私は新しいバインディングのプロトタイプを作成しました。このバインディングは、以下を使用して登録されました。
registry.RegisterFactory(new MvxCustomBindingFactory<MvxBindableListView>("SelectedItem", adapterView => new MvxAdapterViewSelectedItemTargetBinding(adapterView)));
ロジックが含まれています:
using System;
using Android.Widget;
using Cirrious.MvvmCross.Binding.Droid.Views;
using Cirrious.MvvmCross.Binding.Interfaces;
using Cirrious.MvvmCross.Interfaces.Platform.Diagnostics;
namespace Cirrious.MvvmCross.Binding.Droid.Target
{
#warning This needs to be redone for all adapterviews not just list view!
#warning The use of ItemClick instead of ItemSelected needs to be reinvestigated here!
public class MvxAdapterViewSelectedItemTargetBinding : MvxBaseAndroidTargetBinding
{
private readonly MvxBindableListView _view;
private object _currentValue;
public MvxAdapterViewSelectedItemTargetBinding(MvxBindableListView view)
{
_view = view;
((ListView)_view).ItemClick += OnItemClick;
}
private void OnItemClick(object sender, AdapterView.ItemClickEventArgs itemClickEventArgs)
{
var container = (_view.GetItemAtPosition(itemClickEventArgs.Position) as MvxJavaContainer);
if (container == null)
{
MvxBindingTrace.Trace(MvxTraceLevel.Warning, "Missing MvxJavaContainer in MvxAdapterViewSelectedItemTargetBinding");
return;
}
var newValue = container.Object;
if (!newValue.Equals(_currentValue))
{
_currentValue = newValue;
FireValueChanged(newValue);
}
}
public override void SetValue(object value)
{
#warning Sort out Equals test here
if (value != null && value != _currentValue)
{
var index = _view.Adapter.GetPosition(value);
if (index < 0)
{
MvxBindingTrace.Trace(MvxTraceLevel.Warning, "Value not found for spinner {0}", value.ToString());
return;
}
_currentValue = value;
_view.SetSelection(index);
}
}
public override MvxBindingMode DefaultMode
{
get { return MvxBindingMode.TwoWay; }
}
public override Type TargetType
{
get { return typeof(object); }
}
protected override void Dispose(bool isDisposing)
{
if (isDisposing)
{
((ListView)_view).ItemClick -= OnItemClick;
}
base.Dispose(isDisposing);
}
}
}
これが機能することをテストするために、以下を使用して適合させたチュートリアルPullToRefreshコードを使用しました。
<Mvx.MvxBindableListView android:id="@android:id/list" android:layout_width="fill_parent"
android:layout_height="fill_parent"
local:MvxBind="{'ItemsSource':{'Path':'Emails'},'ItemClick':{'Path':'ShowItemCommand'},'SelectedItem':{'Path':'TheSelectedEmail'}}"
local:MvxItemTemplate="@layout/listitem_email"
/>
と:
public class SimpleEmail
{
public string From { get; set; }
public string Header { get; set; }
public string Message { get; set; }
}
private ObservableCollection<SimpleEmail> _emails;
public ObservableCollection<SimpleEmail> Emails
{
get { return _emails; }
private set { _emails = value; RaisePropertyChanged(() => Emails); }
}
private SimpleEmail _email;
public SimpleEmail TheSelectedEmail
{
get { return _email; }
set
{
_email = value;
MvxTrace.Trace(MvxTraceLevel.Error, "HELLO {0} ", value == null ? "null" : value.From);
}
}
このすべての作業で注意すべきことの1つは、Androidのリストビューで選択されたアイテムがSilverlight / wpのリストボックスで選択されたアイテムとわずかに異なることです。たとえば、Androidでリストビューを取得して現在の選択とそれを強調表示するのは非常に難しい場合があります。選択が変更されたイベントを生成するためにリストビューを取得するのは非常に難しい場合があります。
注:Droid SelectedItemの問題をhttps://github.com/slodge/MvvmCross/issues/52に記録しました-近い将来、バインディングがコアライブラリに追加されることを確認します