android - mvxrecyclerview - mvx recycler adapter example



MVVMCross Получить SelectedItem из MvxBindableListView (1)

Маленькая проблема с моим Android-приложением, и я не знаю, как ее решить с помощью MVVM Cross.

Вот моя ViewModel:

public class AddressesShowViewModel : MvxViewModel
{
    public List<Address> Addresses { get; set; }

    public AddressesShowViewModel(string addressesForListView)
    {
        Addresses = JsonConvert.DeserializeObject<List<Address>>(addressesForListView);
    }

    public IMvxCommand ShowItemCommand
    {
        get
        {
            //return new MvxRelayCommand<Type>((type) => this.RequestNavigate(type));
            return new MvxRelayCommand(DoShowContact);
        }
    }

    private Address selectedItem;
    public Address SelectedItem
    {
        get { return selectedItem; }
        set { selectedItem = value; FirePropertyChanged(() => SelectedItem); }
    }

    private void DoShowContact()
    {
        RequestNavigate<AddressShowViewModel>();
    }
}

Мой адрес

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:local="http://schemas.android.com/apk/res/INMobileCRM4Android.INMobileCRM4Android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<Mvx.MvxBindableListView
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    local:MvxBind="{'ItemsSource':{'Path':'Addresses'},'ItemClick':{'Path':'ShowItemCommand'}, 'SelectedItem':{'Path':'SelectedItem'}}"
    local:MvxItemTemplate="@layout/addresslistitem"
  />
</FrameLayout>

Я хотел бы знать, как я могу получить SelectedItem из ListView в AddressesShow.axml .. Я попытался создать Property 'SelectedItem' .. Но его получение вызывает в начале, когда ViewModel создается (и, очевидно, возвращается null), а не при нажатии элемента. Его btw тип адреса, а не только строка или что-то в этом роде. Может быть, какие-то предложения?

https://src-bin.com


Answer #1

Отсутствие SelectedItem в Droid было идентифицировано как проблема на прошлой неделе во время подготовки к разговору Даниэля в Build.

Чтобы обойти это, было несколько быстрых ответов:

1 Существует SelectedItemPosition вы можете использовать для привязки - это int

2 Вы можете использовать привязку 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);
        }
    }
}

Чтобы проверить это, я использовал код Tutorial 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);
        }
    }

Одна вещь, которая должна быть осторожной во всей этой работе, состоит в том, что элемент списка, выбранный в Android, немного отличается от выбранного элемента списка в Silverlight / wp - например, может быть довольно сложно получить список в андроиде, чтобы выделить текущий выбор, и это может быть довольно сложно получить listview для создания выбранных изменений событий.

Примечание. Я зарегистрировал проблему в Droid SelectedItem по адресу https://github.com/slodge/MvvmCross/issues/52. Я буду уверен, что привязка будет добавлена ​​в основную библиотеку в ближайшем будущем.





mvvmcross