使用MVVMCross在iOS上实现搜索

时间:2014-05-14 11:43:40

标签: ios xamarin uisearchbar mvvmcross

我只是想知道是否有任何关于如何做到的例子?

所以我要做的是用MVVCross实现搜索,现在不用如何开始。任何关于正确方向的提示都会受到极大的关注。

值得一提的是,我的想法有点像......

我有一个视图,我有搜索栏。但我不是在该视图中搜索数据。所以在搜索时,我想显示一个新的表视图并搜索它。

我已经为表和控制器创建了一个单元格来显示它(只是usuall列表视图的东西),但我现在仍然坚持使用搜索栏实现。

public partial class HomeView : MvxViewController
{
    public HomeView () : base ("HomeView", null)
    {
    }

    public override void DidReceiveMemoryWarning ()
    {
        // Releases the view if it doesn't have a superview.
        base.DidReceiveMemoryWarning ();

        // Release any cached data, images, etc that aren't in use.
    }

    public override void ViewDidLoad ()
    {
        base.ViewDidLoad ();
        if (RespondsToSelector(new MonoTouch.ObjCRuntime.Selector("edgesForExtendedLayout")))
            EdgesForExtendedLayout = UIRectEdge.None;
        RecommendedCollectionView.RegisterNibForCell(RecommededStationCollectionCell.Nib, RecommededStationCollectionCell.Key);
        var source = new MvxCollectionViewSource(RecommendedCollectionView, RecommededStationCollectionCell.Key);
        RecommendedCollectionView.Source = source;

        var set = this.CreateBindingSet<HomeView, HomeViewModel>();
        set.Bind(source).To(vm => vm.Genres);
        set.Apply();
        RecommendedCollectionView.ReloadData();
        var gesture = new UITapGestureRecognizer (() => {

        });

        View.AddGestureRecognizer (gesture);
    }
}

列表视图:

public class SearchView : UITableViewController
{
    public SearchView () : base ("SearchView", null)
    {
    }

    public override void DidReceiveMemoryWarning ()
    {
        // Releases the view if it doesn't have a superview.
        base.DidReceiveMemoryWarning ();

        // Release any cached data, images, etc that aren't in use.
    }

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


        var source = new MvxSimpleTableViewSource (TableView, SearchTableCell.Key, SearchTableCell.Key);
        TableView.Source = source;
        TableView.RowHeight = 50;

        var set = this.CreateBindingSet<SearchView, SearchViewModel> ();
        set.Bind (source).To (vm => vm.Genres);
        set.Apply ();
        TableView.ReloadData ();
        // Perform any additional setup after loading the view, typically from a nib.
    }
}

总而言之,我想要的是当用户在主视图中的搜索栏中输入内容时,显示searchView列表并搜索内部数据。

感谢。

3 个答案:

答案 0 :(得分:8)

谢谢你们。很抱歉我的视力很晚,所有这些答案都帮助我更好地了解MVVMCross。所以最后,我最终得到了这个解决方案。如果有一些关于这种方法的遗言,如果有人能够指出,我会很高兴。

所以在视图模型中,我有一个字符串属性,它绑定到searh文本。每当有文本更改时,我也会过滤列表。

所以视图模型看起来像这样:

    private string _searchTerm;
    public string SearchTerm 
    {
        get { return _searchTerm; }
        set { 
            _searchTerm = value; 
            if (String.IsNullOrEmpty(_searchTerm)) {
                _genres = new List<Genre> ();
            } else {
                _genres = allGenres.Where (g => g.Name.ToLower ().Contains (_searchTerm.ToLower ())).ToList ();
            }
            RaisePropertyChanged (() => SearchTerm);
            RaisePropertyChanged (() => Genres);
        }
    }

然后考虑它只是绑定它:

set.Bind (SearchBar).For (x=>x.Text).To (vm => vm.SearchTerm);

当然,列表绑定到表源。这就是它的全部。

答案 1 :(得分:4)

不确定这是否是您要找的。我做了类似的事情,当用户开始输入时,我正在刷新正在向用户显示的列表。不确定它是否真的是你想要的,但它对我有用。

/// <summary>
    /// Views the did load.
    /// </summary>
    public override void ViewDidLoad()
    {
        base.ViewDidLoad();
        _searchBar = new UISearchBar(new RectangleF(0, 0, 320, 44))
        {
            AutocorrectionType = UITextAutocorrectionType.Yes
        };
        _searchBar.SearchButtonClicked += SearchBar_SearchButtonClicked;
        _searchBar.TextChanged += SearchBarOnTextChanged;
        _searchBar.CancelButtonClicked += SearchBarOnCancelButtonClicked;

        var source = new MvxSimpleTableViewSource (TableView, SpeciesListCellView.Key, SpeciesListCellView.Key);

        var set = this.CreateBindingSet<SpeciesListView, SpeciesListViewModel> ();
        set.Bind(source).To(vm => vm.Species);

        set.Apply ();

        TableView.RowHeight = 50;
        TableView.Source = source;
        TableView.TableHeaderView = _searchBar;
        TableView.ReloadData ();
    }

然后我连接了处理程序

        /// <summary>
    /// Searches the bar on cancel button clicked.
    /// </summary>
    /// <param name="sender">The sender.</param>
    /// <param name="eventArgs">The <see cref="EventArgs"/> instance containing the event data.</param>
    private void SearchBarOnCancelButtonClicked(object sender, EventArgs eventArgs)
    {
        ((SpeciesListViewModel)ViewModel).SearchSpecieByText(string.Empty);
        BeginInvokeOnMainThread(() => _searchBar.ResignFirstResponder());
    }

    /// <summary>
    /// Searches the bar on text changed.
    /// </summary>
    /// <param name="sender">The sender.</param>
    /// <param name="e">The <see cref="UISearchBarTextChangedEventArgs"/> instance containing the event data.</param>
    private void SearchBarOnTextChanged(object sender, UISearchBarTextChangedEventArgs e)
    {
        if (string.IsNullOrWhiteSpace(_searchBar.Text))
        {
            ((SpeciesListViewModel)ViewModel).SearchSpecieByText(string.Empty);

            BeginInvokeOnMainThread(() => _searchBar.ResignFirstResponder());
        }
        else
        {
            ((SpeciesListViewModel)ViewModel).SearchSpecieByText(_searchBar.Text);
        }
    }

    /// <summary>
    /// Handles the SearchButtonClicked event of the SearchBar control.
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
    private void SearchBar_SearchButtonClicked(object sender, EventArgs e)
    {
        ((SpeciesListViewModel)ViewModel).SearchSpecieByText(_searchBar.Text);
        BeginInvokeOnMainThread(() => _searchBar.ResignFirstResponder());
    }

然后在我的ViewModel中,我只是刷新了列表,确保保留原始列表的完整副本。

        /// <summary>
    /// Searches the specie by text.
    /// </summary>
    /// <param name="text">The text.</param>
    public void SearchSpecieByText(string text)
    {
        if (string.IsNullOrWhiteSpace(text))
            Species = FullSpeciesList;
        else
        {
            Species = FullSpeciesList;
            Species = Species.Where(m => m.Name.ToLowerInvariant().Contains(text.ToLowerInvariant())).ToList();
        }
    }

然后属性Species将调用RaisePropertyChanged方法

答案 2 :(得分:1)

添加到Lipton的答案:如果你想在VM上进行搜索,

选项1)有一个可观察的字典作为源,并且当它更新时,它会引发mvx的事件(对我来说有点太贵)

选项2)拥有正常的源,并在过滤时,在VM中引发某种事件(如弱消息),然后强制视图重新加载数据(无法记住确切的语法,但它& #39; s沿着Table.ReloadData的行。

在View端执行:更简单,因为您只是过滤和更新数据源,并再次重新加载数据。

警告:请记住在搜索栏上取消您订阅的所有活动;理想情况下,不要在ViewDidLoad上连接它,你应该使用ViewWillAppear,并在ViewDidDisappear

时取消连接

另外,searchBar可以有一个委托集(_searchBar.Delegate =),我觉得它有点干净,因为你只有一件事要设置null而不是多个;