我正在尝试使用Xamarin.forms中的MVVM实现搜索栏。到目前为止,我已经设法从互联网上借用了一些代码,而且似乎确实经历了搜索的过程。唯一的问题是我不知道在命令中放入什么代码。
我希望搜索栏从食谱列表中搜索食谱名称。这些信息都存储在本地数据库中,并使用可观察的集合进行显示。
请你帮我解决一下。
XAML
<SearchBar x:Name="SearchBar"
Placeholder="Search"
SearchCommand="{Binding SearchCommand}"
SearchCommandParameter="{Binding Text, Source={x:Reference SearchBar}}"
Text="{Binding SearchText, Mode=TwoWay}">
<SearchBar.Behaviors>
<local:TextChangedBehavior />
</SearchBar.Behaviors>
</SearchBar>
<ListView x:Name="ListViewItems"
ItemsSource="{Binding Recipes}"
IsPullToRefreshEnabled="True"
Refreshing="ListViewItems_Refreshing"
SelectedItem="{Binding SelectedRecipe}">
文本更改了行为
class TextChangedBehavior: Behavior<Xamarin.Forms.SearchBar>
{
protected override void OnAttachedTo(Xamarin.Forms.SearchBar bindable)
{
base.OnAttachedTo(bindable);
bindable.TextChanged += Bindable_TextChanged;
}
protected override void OnDetachingFrom(Xamarin.Forms.SearchBar bindable)
{
base.OnDetachingFrom(bindable);
bindable.TextChanged -= Bindable_TextChanged;
}
private void Bindable_TextChanged(object sender, TextChangedEventArgs e)
{
((Xamarin.Forms.SearchBar)sender).SearchCommand?.Execute(e.NewTextValue);
}
}
和viewModel
public class RecipeListViewModel : ObservableCollection<Recipe>
{
private ObservableCollection<Recipe> Recipes {get; set;}
public INavigation Navigation { get; internal set; }
public ICommand NewAddPage { get; protected set; }
public RecipeListViewModel(INavigation navigation)
{
this.Navigation = navigation;
Recipes = new ObservableCollection<Recipe>();
this.NewAddPage = new Command(async () => await CreateNewAddPage());
Init();
}
// Gets all recipes from the database and adds them to the observable collection
private void Init()
{
var enumarator = App.RecipeDbcontroller.GetRecipe();
if (enumarator == null)
{
App.RecipeDbcontroller.SaveRecipe(new Recipe { RecipeName = "Moussaka", Serves = 6, PrepTime = "30", CookTime = "2 Hours", MealType = "Dinner" });
enumarator = App.RecipeDbcontroller.GetRecipe();
}
while (enumarator.MoveNext())
{
//cleans database of all empty records
if (enumarator.Current.RecipeName == null || enumarator.Current.CookTime == null)
{
App.RecipeDbcontroller.DeleteRecipe(enumarator.Current.RecipeID);
}
else
Add(enumarator.Current);
}
}
private ICommand _searchCommand;
public ICommand SearchCommand
{
get
{
return _searchCommand ?? (_searchCommand = new Command<string>((text) =>
{
**// THIS IS WHAT I DON'T KNOW WHAT TO DO**
}));
}
}
private string _searchText { get; set; }
public string SearchText
{
get { return _searchText; }
set
{
if (_searchText != value)
{
_searchText = value;
}
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
RecipeDatabaseController类
public RecipeDatabaseController()
{
this.database = DependencyService.Get<ISQLite>().GetConnection();
this.database.CreateTable<Recipe>();
}
//Recipe CRUD
public IEnumerator<Recipe> GetRecipe()
{
lock (locker)
{
if (database.Table<Recipe>().Count() == 0)
{
return null;
}
else
{
return this.database.Table<Recipe>().GetEnumerator();
}
}
}
public IEnumerator<Recipe> GetRecipeBySearchTerm(text)
{
var enumarator = GetRecipe();
lock (locker)
{
while (enumarator.MoveNext)
{
if(enumarator.Current.RecipeName.Contains(text)
return this.
}
}
}
public int SaveRecipe(Recipe recipe)
{
lock (locker)
{
if (recipe.RecipeID != 0)
{
this.database.Update(recipe);
return recipe.RecipeID;
}
else
{
return this.database.Insert(recipe);
}
}
}
public int DeleteRecipe(int Id)
{
lock (locker)
{
return this.database.Delete<Recipe>(Id);
}
}
答案 0 :(得分:0)
using System.Linq;
//Recipe CRUD
public IEnumerable<Recipe> GetRecipe()
{
lock (locker)
{
return this.database.Table<Recipe>();
}
}
public IEnumerable<Recipe> GetRecipeBySearchTerm(string text)
{
var recipes = GetRecipe();
lock (locker)
{
return recipes.Where(m => m.RecipeName.ToLower().Contains(text));
}
}
添加using System.Linq
参考
更改这两种方法并返回IEnumerable
注意。 RecipeName
是您用来过滤食谱的属性。
以及您的搜索命令如下
private ICommand _searchCommand;
public ICommand SearchCommand
{
get
{
return _searchCommand ?? (_searchCommand = new Command<string>((text) =>
{
var filteredRecipes = App.RecipeDbcontroller.GetRecipeBySearchTerm(text);
recipes.Clear();
foreach(var recipe in filteredRecipes )
recipes.Add(recipe);
}));
}
}
我尚未测试此代码,所以不确定在哪里出错,但是您可以解决其余问题,因为逻辑已给出
祝你好运
答案 1 :(得分:0)
对,所以搜索命令应该看起来像这样。
public ICommand SearchCommand => _searchCommand ?? (_searchCommand = new Command<string>((text) =>
{
if (text.Length >=1)
{
Recipes.Clear();
Init();
var suggestions = Recipes.Where(c => c.RecipeName.ToLower().StartsWith(text.ToLower())).ToList();
Recipes.Clear();
foreach (var recipe in suggestions)
Recipes.Add(recipe);
}
else
{
Recipes.Clear();
Init();
ListViewVisible = true;
SuggestionsListViewVisible = false;
}
}));