您可以使用 MessagingCenter 来实现它。在每个 Tab Page 中,当SearchBarTextChangeed 发送消息给ViewModel 以更改模型数据。
关于标签页:
<?xml version="1.0" encoding="utf-8"?>
<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:d="http://xamarin.com/schemas/2014/forms/design" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" xmlns:views="clr-namespace:TabbedPageDemo.Views" x:Class="TabbedPageDemo.Views.MainPage">
<TabbedPage.Children>
<NavigationPage Title="Browse">
<NavigationPage.Icon>
<OnPlatform x:TypeArguments="FileImageSource">
<On Platform="iOS" Value="tab_feed.png" />
</OnPlatform>
</NavigationPage.Icon>
<x:Arguments>
<views:ItemsPage />
</x:Arguments>
</NavigationPage>
<NavigationPage Title="About">
<NavigationPage.Icon>
<OnPlatform x:TypeArguments="FileImageSource">
<On Platform="iOS" Value="tab_about.png" />
</OnPlatform>
</NavigationPage.Icon>
<x:Arguments>
<views:AboutPage />
</x:Arguments>
</NavigationPage>
</TabbedPage.Children>
</TabbedPage>
在 One Page 中,其 ViewModel 需要Subscribe MessageCenter :
public class ItemsViewModel : BaseViewModel
{
public ObservableCollection<Item> Items { get; set; }
//Use FilteredItems to show the Filtered Items on ListView
public ObservableCollection<Item> filteredItems;
public ObservableCollection<Item> FilteredItems
{
get { return filteredItems; }
// Use SetProperty to refresh the ListView ItemsSource
set { SetProperty<ObservableCollection<Item>>(ref filteredItems, value); }
}
public Command LoadItemsCommand { get; set; }
public ItemsViewModel()
{
Title = "Browse";
Items = new ObservableCollection<Item>();
FilteredItems = new ObservableCollection<Item>();
LoadItemsCommand = new Command(async () => await ExecuteLoadItemsCommand());
MessagingCenter.Subscribe<NewItemPage, Item>(this, "AddItem", async (obj, item) =>
{
var newItem = item as Item;
Items.Add(newItem);
FilteredItems.Add(newItem);
await DataStore.AddItemAsync(newItem);
});
//use FilterItems Message to filter the text
MessagingCenter.Subscribe<ItemsPage, TextChangedEventArgs>(this, "FilterItems", async (obj, e) =>
{
string filterText = e.NewTextValue;
var Filtered=Items.Where<Item>(item => item.Text.ToLower().Contains(filterText));
if (Filtered != null)
{
//If the filter result is not null, we will update the itemssource to a new array
FilteredItems = new ObservableCollection<Item>(Filtered);
}
else
{
filteredItems = new ObservableCollection<Item>();
}
});
}
async Task ExecuteLoadItemsCommand()
{
if (IsBusy)
return;
IsBusy = true;
try
{
Items.Clear();
var items = await DataStore.GetItemsAsync(true);
foreach (var item in items)
{
Items.Add(item);
FilteredItems.Add(item);
}
}
catch (Exception ex)
{
Debug.WriteLine(ex);
}
finally
{
IsBusy = false;
}
}
}
一页的 Xaml:
<?xml version="1.0" encoding="utf-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:d="http://xamarin.com/schemas/2014/forms/design" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" x:Class="TabbedPageDemo.Views.ItemsPage" Title="{Binding Title}" x:Name="BrowseItemsPage">
<ContentPage.ToolbarItems>
<ToolbarItem Text="Add" Clicked="AddItem_Clicked" />
</ContentPage.ToolbarItems>
<NavigationPage.TitleView>
<SearchBar x:Name="sbSearch" WidthRequest="500" HeightRequest="100" />
</NavigationPage.TitleView>
<StackLayout>
<ListView x:Name="ItemsListView" ItemsSource="{Binding FilteredItems}" VerticalOptions="FillAndExpand" HasUnevenRows="true" RefreshCommand="{Binding LoadItemsCommand}" IsPullToRefreshEnabled="true" IsRefreshing="{Binding IsBusy, Mode=OneWay}" CachingStrategy="RecycleElement" ItemSelected="OnItemSelected">
<d:ListView.ItemsSource>
<x:Array Type="{x:Type x:String}">
<x:String>First Item</x:String>
<x:String>Second Item</x:String>
<x:String>Third Item</x:String>
<x:String>Fourth Item</x:String>
<x:String>Fifth Item</x:String>
<x:String>Sixth Item</x:String>
</x:Array>
</d:ListView.ItemsSource>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Padding="10">
<Label Text="{Binding Text}" d:Text="{Binding .}" LineBreakMode="NoWrap" Style="{DynamicResource ListItemTextStyle}" FontSize="16" />
<Label Text="{Binding Description}" d:Text="Item description" LineBreakMode="NoWrap" Style="{DynamicResource ListItemDetailTextStyle}" FontSize="13" />
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage>
当 SearchBar TextChanged 时,发送消息:
private void SbSearch_TextChanged(object sender, TextChangedEventArgs e)
{
MessagingCenter.Send<ItemsPage, TextChangedEventArgs>(this, "FilterItems", e);
}
这里是Sample Link 供参考。