我在我的 Xamarin.Forms 项目中做了类似的事情,该项目 100% 由 Android 和 iOS 共享 - 没有自定义渲染器。此示例使用 MVVM 模式和一些代码隐藏。我的视图模型包含 ListView 绑定到的对象的 IList。当用户使用查询表达式按下三个或更多字符时,它会更新。
private IList<myObject> results;
public IList<myObject> QueryResults
{
get
{
return results;
}
set
{
SetProperty(ref results, value);
}
}
在 OnTextChanged 处理程序中,我运行查询表达式并在每次击键时填充 QueryResults。这可能效率不高,但效果很好。
所以视图标记和代码隐藏是这样的:
<StackLayout>
<Label Style="{StaticResource formLabel}" Text="My Searchable List" />
<!-- from poc -->
<Grid WidthRequest="550">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="AUTO" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="350" />
</Grid.ColumnDefinitions>
<Frame Grid.Row="0" Style="{StaticResource InputFrame}" HeightRequest="49">
<Entry x:Name="SearchText" Style="{StaticResource formLabel}" WidthRequest="550" HeightRequest="45" Text="{Binding SearchString, Mode=TwoWay}" TextChanged="Handle_TextChanged" />
</Frame>
<StackLayout Grid.Row="1" Orientation="Horizontal">
<Frame x:Name="MyObjectFrame" Style="{StaticResource InputFrame}" HeightRequest="{Binding ListHeight}" HasShadow="true">
<ListView x:Name="MyObjectList" ItemsSource="{Binding ResultantMyObjects}" ItemSelected="OnItemSelected" HeightRequest="{Binding ListHeight}">
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="{Binding Name}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Frame>
</StackLayout>
在代码隐藏中使用 Handle_TextChanged:
void Handle_TextChanged(object sender, Xamarin.Forms.TextChangedEventArgs e)
{
if (e.NewTextValue.Length > 2)
{
(BindingContext as SampleDetailsViewModel).MySIteSearchResults(e.NewTextValue);
this.ForceLayout();// force the change in heightrequest for ListView
MyObjectList.IsVisible = true;
MyObjectFrame.IsVisible = true;
}
else
{
MyObjectList.IsVisible = false;
MyObjectFrame.IsVisible = false;
}
}
在视图模型中,我更新了上面的属性,注意返回值并没有在这个还不完美的例子中使用:
public List<MyObjectDTO> MyObjectSearchResults(string keystrokes)
{
//TODO: encapsulate in a View
List<MyObjectDTO> searchResults = null;
IEnumerable<MyObjectDTO> queryResults;
queryResults = from site in MyObjects
where site.Name.ToLower().Contains(keystrokes.ToLower())
select site;
if (string.IsNullOrEmpty(SearchString))
{
QueryResults = MyObjects;
}
else
{
QueryResults = queryResults.ToList<MyObjectDTO>();
ListHeight = QueryResults.Count * 45; //TODO: detect size. magic number of 45 limits the height.
}
return searchResults;
}
注意:可能会有一些错误,因为我必须清理一些代码。