Реализация UISearchController с использованием MVVMCross - PullRequest
0 голосов
/ 20 марта 2019

У меня есть приложение, которое я конвертирую из iOS только в iOS и Droid, используя MVVMCross.

В моем текущем приложении у меня есть вид карты, который использует UISearchController, который позволяет пользователю искать местоположения поблизости.Это основано на примере Xamarin и работает нормально: Пример карты Xamarin

Для преобразования у меня есть:

  1. MapView, привязанный к MapViewModel.
  2. Служба поиска, которая внедряется в MapViewModel.
  3. Создает UISearchController и привязывает текст поиска к свойству в MapViewModel.

При обновлении текстапоиск вызван, и результаты получены.Я борюсь с тем, как привязать результаты обратно к SearchResultsView, как это представлено UISearchController.

Может кто-нибудь дать мне совет или указать правильное направление для решения этой проблемы.

У меня есть фрагмент кода ниже, чтобы дать представление о том, на что я рассчитывал.

    [MvxFromStoryboard]
public partial class MapView : MvxViewController<MapViewModel>
{


    public MapView(IntPtr handle) : base(handle)
    {
    }

    public override void ViewDidLoad()
    {
        base.ViewDidLoad();

        var searchResultsController = new SearchResultsView();

        //Not sure if this is required
        //var searchUpdater.UpdateSearchResults += searchResultsController.Search;

        var searchController = new UISearchController(searchResultsController)
        {
            //Nore sure if this is required
            //SearchResultsUpdater = searchUpdater
        };


        searchController.SearchBar.SizeToFit();
        searchController.SearchBar.SearchBarStyle = UISearchBarStyle.Minimal;
        searchController.SearchBar.Placeholder = "Enter a search query";
        searchController.HidesNavigationBarDuringPresentation = false;
        DefinesPresentationContext = true;
        NavigationItem.TitleView = searchController.SearchBar;

        //Bind to View Model
        var set = this.CreateBindingSet<MapView, MapViewModel>();
        set.Bind(searchController.SearchBar).To(vm => vm.SearchQuery);
        set.Apply();
    }

}

public class SearchResultsUpdator : UISearchResultsUpdating
{
    public event Action<string> UpdateSearchResults = delegate { };

    public override void UpdateSearchResultsForSearchController(UISearchController searchController)
    {
        this.UpdateSearchResults(searchController.SearchBar.Text);
    }
}


[MvxFromStoryboard]
public partial class SearchResultsView : MvxTableViewController<SearchResultsViewModel>
{
    public SearchResultsView() { }

    public SearchResultsView(IntPtr handle) : base(handle)
    {
    }

    public override void ViewDidLoad()
    {
        base.ViewDidLoad();

        var source = new SearchResultsTableViewSource(TableView);
        TableView.Source = source;

        var set = this.CreateBindingSet<SearchResultsView, SearchResultsViewModel>();
        set.Bind(source).To(vm => vm.Results);
        set.Apply();


    }
}

[MvxFromStoryboard]
public partial class SearchResultsView : MvxTableViewController<SearchResultsViewModel>
{
    public SearchResultsView() { }

    public SearchResultsView(IntPtr handle) : base(handle)
    {
    }

    public override void ViewDidLoad()
    {
        base.ViewDidLoad();

        var source = new SearchResultsTableViewSource(TableView);
        TableView.Source = source;

        var set = this.CreateBindingSet<SearchResultsView, SearchResultsViewModel>();
        set.Bind(source).To(vm => vm.Results);
        set.Apply();


    }
}

1 Ответ

0 голосов
/ 29 марта 2019

Я разместил это на тот случай, если кто-то другой ищет пример. Я решил, что лучший способ сделать это - позволить iOS обрабатывать контроллер представления поиска для результатов. Кодекс следует. Не стесняйтесь исправлять или предлагать лучшую альтернативу

View

    [MvxFromStoryboard]
    public partial class MapView : MvxViewController
    {
        UISearchController _searchController;
        SearchResultsViewController _searchResultsController;

        private IDisposable _searchResultsUpdateSubscription;
        private IMvxInteraction _searchResultsUpdatedInteraction;
        public IMvxInteraction SearchResultsUpdatedInteraction
        {
            get => _searchResultsUpdatedInteraction;
            set
            {
                if (_searchResultsUpdateSubscription != null)
                {
                    _searchResultsUpdateSubscription.Dispose();
                    _searchResultsUpdateSubscription = null;
                }

                _searchResultsUpdatedInteraction = value;
                if (_searchResultsUpdatedInteraction != null)
                {
                    _searchResultsUpdateSubscription = _searchResultsUpdatedInteraction.WeakSubscribe(OnSearchResultsUpdated);
                }
            }
        }


        private void OnSearchResultsUpdated(object sender, EventArgs e)
        {
            _searchResultsController.SearchResults = Results;
            _searchResultsController.ReloadSearchTable();
        }

        public List<Placemark> Results { get; set; }

        public MapView(IntPtr handle) : base(handle)
        {
        }

        public override void ViewDidLoad()
        {
            base.ViewDidLoad();

            //Bind to View Model
            var set = this.CreateBindingSet<MapView, MapViewModel>();
            set.Bind(_searchController.SearchBar).To(vm => vm.SearchQuery);
            set.Bind(this).For(v => v.Results).To(vm => vm.Results);
            set.Bind(this).For(v => v.SearchResultsUpdatedInteraction).To(vm => vm.SearchResultsUpdatedInteraction).OneWay();
            set.Apply();

        }

ViewModel

    public class MapViewModel : MvxViewModel
    {
        readonly ILocationService _locationService;

        private MvxInteraction _searchResultsUpdatedInteraction = new MvxInteraction();
        public IMvxInteraction SearchResultsUpdatedInteraction => _searchResultsUpdatedInteraction;

        public MapViewModel(ILocationService locationService)
        {
            _locationService = locationService;
        }
        //***** Properties *****

        private List<Placemark> _results;
        public List<Placemark> Results
        {
            get => _results;
            set
            {
                _results = value;
                RaisePropertyChanged();
            }
        }

        private string _searchQuery;
        public string SearchQuery
        {
            get => _searchQuery;
            set
            {
                _searchQuery = value;
                //Task.Run(UpdateResultsAsync).Wait();
                RaisePropertyChanged();
                UpdateResultsAsync();
            }
        }

        //***** Privates *****
        private async Task UpdateResultsAsync()
        {
            Results = await _locationService.SearchForPlacesAsync(_searchQuery);
            _searchResultsUpdatedInteraction.Raise();
        }
    }

SearchResultsViewController

    public class SearchResultsViewController : UITableViewController
    {
        static readonly string mapItemCellId = "mapItemCellId";

        public List<Placemark> SearchResults { get; set; }

        public SearchResultsViewController()
        {

            SearchResults = new List<Placemark>();
        }

        public override nint RowsInSection(UITableView tableView, nint section)
        {
            return SearchResults == null ? 0 : SearchResults.Count;
        }

        public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
        {
            var cell = tableView.DequeueReusableCell(mapItemCellId);

            if (cell == null)
                cell = new UITableViewCell();

            cell.TextLabel.Text = SearchResults[indexPath.Row].FeatureName;
            return cell;
        }

        public override void RowSelected(UITableView tableView, NSIndexPath indexPath)
        {
           //Do stuff here
        }

        public void ReloadSearchTable()
        {
            this.TableView.ReloadData();
        }
    }

...