Xamarin Forms:如何处理从视图到视图模型的订阅事件(ListView - 搜索栏)
Xamarin Forms: How to handle a subcribe event from view to viewmodel (ListView - Search Bar)
全部,
我正在构建绑定 SearchText 的自定义 SearchableListView 属性。
public class SearchableListView : SfListView
{
#region Field
/// <summary>
/// Gets or sets the text value used to search.
/// </summary>
public static readonly BindableProperty SearchTextProperty =
BindableProperty.Create(nameof(SearchText), typeof(string), typeof(SearchableListView), null, BindingMode.Default, null, OnSearchTextChanged);
/// <summary>
/// Gets or sets the text value used to search.
/// </summary>
private string searchText;
#endregion
#region Property
/// <summary>
/// Gets or sets the text value used to search.
/// </summary>
public string SearchText
{
get
{
return (string)this.GetValue(SearchTextProperty);
}
set
{
this.SetValue(SearchTextProperty, value);
}
}
#endregion
#region Method
/// <summary>
/// Filtering the list view items based on the search text.
/// </summary>
/// <param name="obj">The list view item</param>
/// <returns>Returns the filtered item</returns>
public virtual bool FilterData(object obj)
{
if (this.SearchText == null)
{
return false;
}
return true;
}
/// <summary>
/// Invoked when the search text is changed.
/// </summary>
/// <param name="bindable">The SfListView</param>
/// <param name="oldValue">The old value</param>
/// <param name="newValue">The new value</param>
private static void OnSearchTextChanged(BindableObject bindable, object oldValue, object newValue)
{
var listView = bindable as SearchableListView;
if (newValue != null && listView.DataSource != null)
{
listView.searchText = (string)newValue;
listView.DataSource.Filter = listView.FilterData;
listView.DataSource.RefreshFilter();
}
listView.RefreshView();
}
#endregion
}
此视图绑定到通用列表项,因此 FilterData 上的对象可以是任何类型。
IDK 如何将事件订阅到 FilterData,它在视图模型上执行方法,我可以在其中将我的对象转换为我已知的类型。
这是我的 ViewModel。
public abstract class ListPageViewModel<T> : BaseViewModel where T : class, IEntity
{
private T _selectedItem;
private string searchText;
private ObservableCollection<T> _items;
public ListPageViewModel()
{
this.NewCommand = new Command(NewItem);
this.ItemSelectedCommand = new Command(ItemSelected);
}
public ObservableCollection<T> Items
{
get => _items;
set
{
this.SetProperty(ref this._items, value);
}
}
public T SelectedItem
{
get => _selectedItem;
set
{
this.SetProperty(ref this._selectedItem, value);
}
}
public string SearchText
{
get => searchText;
set
{
this.SetProperty(ref this.searchText, value);
}
}
public ICommand NewCommand { get; set; }
public ICommand ItemSelectedCommand { get; set; }
public async virtual void LoadItemsAsync()
{
Items = new ObservableCollection<T>(await localDataService.GetAllAsync<T>());
}
public async virtual void NewItem(object obj)
{
}
public async virtual void ItemSelected(object obj)
{
var eventArgs = obj as Syncfusion.ListView.XForms.ItemTappedEventArgs;
navigationService.NavigateTo(EditViewModel, "editEntity", eventArgs.ItemData, false);
await MtTaskExtensions.CompletedTask;
}
}
既然是虚方法,难道就不能像这样重写ViewModel中的方法吗?
public class MyListPageViewModel : ListPageViewModel<MyClass>
{
public override bool FilterData(object obj)
{
if(obj is MyClass myObj)
{
// Do something
}
return base
.FilterData(obj);
}
}
全部,
我正在构建绑定 SearchText 的自定义 SearchableListView 属性。
public class SearchableListView : SfListView
{
#region Field
/// <summary>
/// Gets or sets the text value used to search.
/// </summary>
public static readonly BindableProperty SearchTextProperty =
BindableProperty.Create(nameof(SearchText), typeof(string), typeof(SearchableListView), null, BindingMode.Default, null, OnSearchTextChanged);
/// <summary>
/// Gets or sets the text value used to search.
/// </summary>
private string searchText;
#endregion
#region Property
/// <summary>
/// Gets or sets the text value used to search.
/// </summary>
public string SearchText
{
get
{
return (string)this.GetValue(SearchTextProperty);
}
set
{
this.SetValue(SearchTextProperty, value);
}
}
#endregion
#region Method
/// <summary>
/// Filtering the list view items based on the search text.
/// </summary>
/// <param name="obj">The list view item</param>
/// <returns>Returns the filtered item</returns>
public virtual bool FilterData(object obj)
{
if (this.SearchText == null)
{
return false;
}
return true;
}
/// <summary>
/// Invoked when the search text is changed.
/// </summary>
/// <param name="bindable">The SfListView</param>
/// <param name="oldValue">The old value</param>
/// <param name="newValue">The new value</param>
private static void OnSearchTextChanged(BindableObject bindable, object oldValue, object newValue)
{
var listView = bindable as SearchableListView;
if (newValue != null && listView.DataSource != null)
{
listView.searchText = (string)newValue;
listView.DataSource.Filter = listView.FilterData;
listView.DataSource.RefreshFilter();
}
listView.RefreshView();
}
#endregion
}
此视图绑定到通用列表项,因此 FilterData 上的对象可以是任何类型。 IDK 如何将事件订阅到 FilterData,它在视图模型上执行方法,我可以在其中将我的对象转换为我已知的类型。
这是我的 ViewModel。
public abstract class ListPageViewModel<T> : BaseViewModel where T : class, IEntity
{
private T _selectedItem;
private string searchText;
private ObservableCollection<T> _items;
public ListPageViewModel()
{
this.NewCommand = new Command(NewItem);
this.ItemSelectedCommand = new Command(ItemSelected);
}
public ObservableCollection<T> Items
{
get => _items;
set
{
this.SetProperty(ref this._items, value);
}
}
public T SelectedItem
{
get => _selectedItem;
set
{
this.SetProperty(ref this._selectedItem, value);
}
}
public string SearchText
{
get => searchText;
set
{
this.SetProperty(ref this.searchText, value);
}
}
public ICommand NewCommand { get; set; }
public ICommand ItemSelectedCommand { get; set; }
public async virtual void LoadItemsAsync()
{
Items = new ObservableCollection<T>(await localDataService.GetAllAsync<T>());
}
public async virtual void NewItem(object obj)
{
}
public async virtual void ItemSelected(object obj)
{
var eventArgs = obj as Syncfusion.ListView.XForms.ItemTappedEventArgs;
navigationService.NavigateTo(EditViewModel, "editEntity", eventArgs.ItemData, false);
await MtTaskExtensions.CompletedTask;
}
}
既然是虚方法,难道就不能像这样重写ViewModel中的方法吗?
public class MyListPageViewModel : ListPageViewModel<MyClass>
{
public override bool FilterData(object obj)
{
if(obj is MyClass myObj)
{
// Do something
}
return base
.FilterData(obj);
}
}